iwl-debugfs.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 Intel Corporation. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of version 2 of the GNU General Public License as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  19. * USA
  20. *
  21. * The full GNU General Public License is included in this distribution
  22. * in the file called LICENSE.GPL.
  23. *
  24. * Contact Information:
  25. * Tomas Winkler <tomas.winkler@intel.com>
  26. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  27. *****************************************************************************/
  28. #include <linux/kernel.h>
  29. #include <linux/module.h>
  30. #include <linux/debugfs.h>
  31. #include <linux/ieee80211.h>
  32. #include <net/mac80211.h>
  33. #include "iwl-4965.h"
  34. #include "iwl-debug.h"
  35. #include "iwl-io.h"
  36. /* create and remove of files */
  37. #define DEBUGFS_ADD_DIR(name, parent) do { \
  38. dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
  39. if (!(dbgfs->dir_##name)) \
  40. goto err; \
  41. } while (0)
  42. #define DEBUGFS_ADD_FILE(name, parent) do { \
  43. dbgfs->dbgfs_##parent##_files.file_##name = \
  44. debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
  45. &iwl_dbgfs_##name##_ops); \
  46. if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
  47. goto err; \
  48. } while (0)
  49. #define DEBUGFS_REMOVE(name) do { \
  50. debugfs_remove(name); \
  51. name = NULL; \
  52. } while (0);
  53. /* file operation */
  54. #define DEBUGFS_READ_FUNC(name) \
  55. static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
  56. char __user *user_buf, \
  57. size_t count, loff_t *ppos);
  58. #define DEBUGFS_WRITE_FUNC(name) \
  59. static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
  60. const char __user *user_buf, \
  61. size_t count, loff_t *ppos);
  62. static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
  63. {
  64. file->private_data = inode->i_private;
  65. return 0;
  66. }
  67. #define DEBUGFS_READ_FILE_OPS(name) \
  68. DEBUGFS_READ_FUNC(name); \
  69. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  70. .read = iwl_dbgfs_##name##_read, \
  71. .open = iwl_dbgfs_open_file_generic, \
  72. };
  73. #define DEBUGFS_READ_WRITE_FILE_OPS(name) \
  74. DEBUGFS_READ_FUNC(name); \
  75. DEBUGFS_WRITE_FUNC(name); \
  76. static const struct file_operations iwl_dbgfs_##name##_ops = { \
  77. .write = iwl_dbgfs_##name##_write, \
  78. .read = iwl_dbgfs_##name##_read, \
  79. .open = iwl_dbgfs_open_file_generic, \
  80. };
  81. static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
  82. char __user *user_buf,
  83. size_t count, loff_t *ppos) {
  84. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  85. char buf[256];
  86. int pos = 0;
  87. pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt);
  88. pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt);
  89. pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt);
  90. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  91. }
  92. static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
  93. char __user *user_buf,
  94. size_t count, loff_t *ppos) {
  95. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  96. char buf[256];
  97. int pos = 0;
  98. pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt);
  99. pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt);
  100. pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt);
  101. return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  102. }
  103. #define BYTE1_MASK 0x000000ff;
  104. #define BYTE2_MASK 0x0000ffff;
  105. #define BYTE3_MASK 0x00ffffff;
  106. static ssize_t iwl_dbgfs_sram_read(struct file *file,
  107. char __user *user_buf,
  108. size_t count, loff_t *ppos)
  109. {
  110. u32 val;
  111. char buf[1024];
  112. ssize_t ret;
  113. int i;
  114. int pos = 0;
  115. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  116. printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
  117. priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
  118. iwl_grab_nic_access(priv);
  119. for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
  120. val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
  121. priv->dbgfs->sram_len - i);
  122. if (i < 4) {
  123. switch (i) {
  124. case 1:
  125. val &= BYTE1_MASK;
  126. break;
  127. case 2:
  128. val &= BYTE2_MASK;
  129. break;
  130. case 3:
  131. val &= BYTE3_MASK;
  132. break;
  133. }
  134. }
  135. pos += sprintf(buf+pos, "0x%08x ", val);
  136. }
  137. pos += sprintf(buf+pos, "\n");
  138. iwl_release_nic_access(priv);
  139. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  140. return ret;
  141. }
  142. static ssize_t iwl_dbgfs_sram_write(struct file *file,
  143. const char __user *user_buf,
  144. size_t count, loff_t *ppos)
  145. {
  146. struct iwl_priv *priv = file->private_data;
  147. char buf[64];
  148. int buf_size;
  149. u32 offset, len;
  150. memset(buf, 0, sizeof(buf));
  151. buf_size = min(count, sizeof(buf) - 1);
  152. if (copy_from_user(buf, user_buf, buf_size))
  153. return -EFAULT;
  154. if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
  155. priv->dbgfs->sram_offset = offset;
  156. priv->dbgfs->sram_len = len;
  157. } else {
  158. priv->dbgfs->sram_offset = 0;
  159. priv->dbgfs->sram_len = 0;
  160. }
  161. return count;
  162. }
  163. static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
  164. size_t count, loff_t *ppos)
  165. {
  166. struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
  167. struct iwl4965_station_entry *station;
  168. int max_sta = priv->hw_setting.max_stations;
  169. char *buf;
  170. int i, j, pos = 0;
  171. ssize_t ret;
  172. /* Add 30 for initial string */
  173. const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
  174. DECLARE_MAC_BUF(mac);
  175. buf = kmalloc(bufsz, GFP_KERNEL);
  176. if(!buf)
  177. return -ENOMEM;
  178. pos += sprintf(buf+pos, "num of stations: %d\n\n",
  179. priv->num_stations);
  180. for (i = 0; i < max_sta; i++) {
  181. station = &priv->stations[i];
  182. if (station->used) {
  183. pos += sprintf(buf+pos, "station %d:\ngeneral data:\n",
  184. i+1);
  185. print_mac(mac, station->sta.sta.addr);
  186. pos += sprintf(buf+pos, "id: %u\n",
  187. station->sta.sta.sta_id);
  188. pos += sprintf(buf+pos, "mode: %u\n",
  189. station->sta.mode);
  190. pos += sprintf(buf+pos, "flags: 0x%x\n",
  191. station->sta.station_flags_msk);
  192. pos += sprintf(buf+pos, "ps_status: %u\n",
  193. station->ps_status);
  194. pos += sprintf(buf+pos, "tid data:\n");
  195. pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t");
  196. pos += sprintf(buf+pos, "frame_count\twait_for_ba\t");
  197. pos += sprintf(buf+pos, "start_idx\tbitmap0\t");
  198. pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n");
  199. for (j = 0; j < MAX_TID_COUNT; j++) {
  200. pos += sprintf(buf+pos, "[%d]:\t\t%u\t",
  201. j, station->tid[j].seq_number);
  202. pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t",
  203. station->tid[j].agg.txq_id,
  204. station->tid[j].agg.frame_count,
  205. station->tid[j].agg.wait_for_ba);
  206. pos += sprintf(buf+pos, "%u\t%llu\t%u\n",
  207. station->tid[j].agg.start_idx,
  208. station->tid[j].agg.bitmap,
  209. station->tid[j].agg.rate_n_flags);
  210. }
  211. pos += sprintf(buf+pos, "\n");
  212. }
  213. }
  214. ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
  215. kfree(buf);
  216. return ret;
  217. }
  218. DEBUGFS_READ_WRITE_FILE_OPS(sram);
  219. DEBUGFS_READ_FILE_OPS(stations);
  220. DEBUGFS_READ_FILE_OPS(rx_statistics);
  221. DEBUGFS_READ_FILE_OPS(tx_statistics);
  222. /*
  223. * Create the debugfs files and directories
  224. *
  225. */
  226. int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
  227. {
  228. struct iwl_debugfs *dbgfs;
  229. dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
  230. if (!dbgfs) {
  231. goto err;
  232. }
  233. priv->dbgfs = dbgfs;
  234. dbgfs->name = name;
  235. dbgfs->dir_drv = debugfs_create_dir(name, NULL);
  236. if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
  237. goto err;
  238. }
  239. DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
  240. DEBUGFS_ADD_FILE(sram, data);
  241. DEBUGFS_ADD_FILE(stations, data);
  242. DEBUGFS_ADD_FILE(rx_statistics, data);
  243. DEBUGFS_ADD_FILE(tx_statistics, data);
  244. return 0;
  245. err:
  246. IWL_ERROR("Can't open the debugfs directory\n");
  247. iwl_dbgfs_unregister(priv);
  248. return -ENOENT;
  249. }
  250. EXPORT_SYMBOL(iwl_dbgfs_register);
  251. /**
  252. * Remove the debugfs files and directories
  253. *
  254. */
  255. void iwl_dbgfs_unregister(struct iwl_priv *priv)
  256. {
  257. if (!(priv->dbgfs))
  258. return;
  259. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
  260. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
  261. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
  262. DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
  263. DEBUGFS_REMOVE(priv->dbgfs->dir_data);
  264. DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
  265. kfree(priv->dbgfs);
  266. priv->dbgfs = NULL;
  267. }
  268. EXPORT_SYMBOL(iwl_dbgfs_unregister);