htc_drv_debug.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * Copyright (c) 2010-2011 Atheros Communications 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 "htc.h"
  17. static struct dentry *ath9k_debugfs_root;
  18. static int ath9k_debugfs_open(struct inode *inode, struct file *file)
  19. {
  20. file->private_data = inode->i_private;
  21. return 0;
  22. }
  23. static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
  24. size_t count, loff_t *ppos)
  25. {
  26. struct ath9k_htc_priv *priv = file->private_data;
  27. struct ath9k_htc_target_stats cmd_rsp;
  28. char buf[512];
  29. unsigned int len = 0;
  30. int ret = 0;
  31. memset(&cmd_rsp, 0, sizeof(cmd_rsp));
  32. WMI_CMD(WMI_TGT_STATS_CMDID);
  33. if (ret)
  34. return -EINVAL;
  35. len += snprintf(buf + len, sizeof(buf) - len,
  36. "%19s : %10u\n", "TX Short Retries",
  37. be32_to_cpu(cmd_rsp.tx_shortretry));
  38. len += snprintf(buf + len, sizeof(buf) - len,
  39. "%19s : %10u\n", "TX Long Retries",
  40. be32_to_cpu(cmd_rsp.tx_longretry));
  41. len += snprintf(buf + len, sizeof(buf) - len,
  42. "%19s : %10u\n", "TX Xretries",
  43. be32_to_cpu(cmd_rsp.tx_xretries));
  44. len += snprintf(buf + len, sizeof(buf) - len,
  45. "%19s : %10u\n", "TX Unaggr. Xretries",
  46. be32_to_cpu(cmd_rsp.ht_txunaggr_xretry));
  47. len += snprintf(buf + len, sizeof(buf) - len,
  48. "%19s : %10u\n", "TX Xretries (HT)",
  49. be32_to_cpu(cmd_rsp.ht_tx_xretries));
  50. len += snprintf(buf + len, sizeof(buf) - len,
  51. "%19s : %10u\n", "TX Rate", priv->debug.txrate);
  52. if (len > sizeof(buf))
  53. len = sizeof(buf);
  54. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  55. }
  56. static const struct file_operations fops_tgt_stats = {
  57. .read = read_file_tgt_stats,
  58. .open = ath9k_debugfs_open,
  59. .owner = THIS_MODULE,
  60. .llseek = default_llseek,
  61. };
  62. static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
  63. size_t count, loff_t *ppos)
  64. {
  65. struct ath9k_htc_priv *priv = file->private_data;
  66. char buf[512];
  67. unsigned int len = 0;
  68. len += snprintf(buf + len, sizeof(buf) - len,
  69. "%20s : %10u\n", "Buffers queued",
  70. priv->debug.tx_stats.buf_queued);
  71. len += snprintf(buf + len, sizeof(buf) - len,
  72. "%20s : %10u\n", "Buffers completed",
  73. priv->debug.tx_stats.buf_completed);
  74. len += snprintf(buf + len, sizeof(buf) - len,
  75. "%20s : %10u\n", "SKBs queued",
  76. priv->debug.tx_stats.skb_queued);
  77. len += snprintf(buf + len, sizeof(buf) - len,
  78. "%20s : %10u\n", "SKBs success",
  79. priv->debug.tx_stats.skb_success);
  80. len += snprintf(buf + len, sizeof(buf) - len,
  81. "%20s : %10u\n", "SKBs failed",
  82. priv->debug.tx_stats.skb_failed);
  83. len += snprintf(buf + len, sizeof(buf) - len,
  84. "%20s : %10u\n", "CAB queued",
  85. priv->debug.tx_stats.cab_queued);
  86. len += snprintf(buf + len, sizeof(buf) - len,
  87. "%20s : %10u\n", "BE queued",
  88. priv->debug.tx_stats.queue_stats[WME_AC_BE]);
  89. len += snprintf(buf + len, sizeof(buf) - len,
  90. "%20s : %10u\n", "BK queued",
  91. priv->debug.tx_stats.queue_stats[WME_AC_BK]);
  92. len += snprintf(buf + len, sizeof(buf) - len,
  93. "%20s : %10u\n", "VI queued",
  94. priv->debug.tx_stats.queue_stats[WME_AC_VI]);
  95. len += snprintf(buf + len, sizeof(buf) - len,
  96. "%20s : %10u\n", "VO queued",
  97. priv->debug.tx_stats.queue_stats[WME_AC_VO]);
  98. if (len > sizeof(buf))
  99. len = sizeof(buf);
  100. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  101. }
  102. static const struct file_operations fops_xmit = {
  103. .read = read_file_xmit,
  104. .open = ath9k_debugfs_open,
  105. .owner = THIS_MODULE,
  106. .llseek = default_llseek,
  107. };
  108. void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
  109. struct ath_htc_rx_status *rxs)
  110. {
  111. #define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++
  112. if (rxs->rs_status & ATH9K_RXERR_CRC)
  113. priv->debug.rx_stats.err_crc++;
  114. if (rxs->rs_status & ATH9K_RXERR_DECRYPT)
  115. priv->debug.rx_stats.err_decrypt_crc++;
  116. if (rxs->rs_status & ATH9K_RXERR_MIC)
  117. priv->debug.rx_stats.err_mic++;
  118. if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
  119. priv->debug.rx_stats.err_pre_delim++;
  120. if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST)
  121. priv->debug.rx_stats.err_post_delim++;
  122. if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY)
  123. priv->debug.rx_stats.err_decrypt_busy++;
  124. if (rxs->rs_status & ATH9K_RXERR_PHY) {
  125. priv->debug.rx_stats.err_phy++;
  126. if (rxs->rs_phyerr < ATH9K_PHYERR_MAX)
  127. RX_PHY_ERR_INC(rxs->rs_phyerr);
  128. }
  129. #undef RX_PHY_ERR_INC
  130. }
  131. static ssize_t read_file_recv(struct file *file, char __user *user_buf,
  132. size_t count, loff_t *ppos)
  133. {
  134. #define PHY_ERR(s, p) \
  135. len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \
  136. priv->debug.rx_stats.err_phy_stats[p]);
  137. struct ath9k_htc_priv *priv = file->private_data;
  138. char *buf;
  139. unsigned int len = 0, size = 1500;
  140. ssize_t retval = 0;
  141. buf = kzalloc(size, GFP_KERNEL);
  142. if (buf == NULL)
  143. return -ENOMEM;
  144. len += snprintf(buf + len, size - len,
  145. "%20s : %10u\n", "SKBs allocated",
  146. priv->debug.rx_stats.skb_allocated);
  147. len += snprintf(buf + len, size - len,
  148. "%20s : %10u\n", "SKBs completed",
  149. priv->debug.rx_stats.skb_completed);
  150. len += snprintf(buf + len, size - len,
  151. "%20s : %10u\n", "SKBs Dropped",
  152. priv->debug.rx_stats.skb_dropped);
  153. len += snprintf(buf + len, size - len,
  154. "%20s : %10u\n", "CRC ERR",
  155. priv->debug.rx_stats.err_crc);
  156. len += snprintf(buf + len, size - len,
  157. "%20s : %10u\n", "DECRYPT CRC ERR",
  158. priv->debug.rx_stats.err_decrypt_crc);
  159. len += snprintf(buf + len, size - len,
  160. "%20s : %10u\n", "MIC ERR",
  161. priv->debug.rx_stats.err_mic);
  162. len += snprintf(buf + len, size - len,
  163. "%20s : %10u\n", "PRE-DELIM CRC ERR",
  164. priv->debug.rx_stats.err_pre_delim);
  165. len += snprintf(buf + len, size - len,
  166. "%20s : %10u\n", "POST-DELIM CRC ERR",
  167. priv->debug.rx_stats.err_post_delim);
  168. len += snprintf(buf + len, size - len,
  169. "%20s : %10u\n", "DECRYPT BUSY ERR",
  170. priv->debug.rx_stats.err_decrypt_busy);
  171. len += snprintf(buf + len, size - len,
  172. "%20s : %10u\n", "TOTAL PHY ERR",
  173. priv->debug.rx_stats.err_phy);
  174. PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
  175. PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
  176. PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
  177. PHY_ERR("RATE", ATH9K_PHYERR_RATE);
  178. PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH);
  179. PHY_ERR("RADAR", ATH9K_PHYERR_RADAR);
  180. PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE);
  181. PHY_ERR("TOR", ATH9K_PHYERR_TOR);
  182. PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING);
  183. PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
  184. PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
  185. PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
  186. PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP);
  187. PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE);
  188. PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART);
  189. PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT);
  190. PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING);
  191. PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC);
  192. PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
  193. PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE);
  194. PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART);
  195. PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
  196. PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP);
  197. PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR);
  198. PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
  199. PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
  200. if (len > size)
  201. len = size;
  202. retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  203. kfree(buf);
  204. return retval;
  205. #undef PHY_ERR
  206. }
  207. static const struct file_operations fops_recv = {
  208. .read = read_file_recv,
  209. .open = ath9k_debugfs_open,
  210. .owner = THIS_MODULE,
  211. .llseek = default_llseek,
  212. };
  213. static ssize_t read_file_slot(struct file *file, char __user *user_buf,
  214. size_t count, loff_t *ppos)
  215. {
  216. struct ath9k_htc_priv *priv = file->private_data;
  217. char buf[512];
  218. unsigned int len = 0;
  219. spin_lock_bh(&priv->tx.tx_lock);
  220. len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : ");
  221. len += bitmap_scnprintf(buf + len, sizeof(buf) - len,
  222. priv->tx.tx_slot, MAX_TX_BUF_NUM);
  223. len += snprintf(buf + len, sizeof(buf) - len, "\n");
  224. len += snprintf(buf + len, sizeof(buf) - len,
  225. "Used slots : %d\n",
  226. bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM));
  227. spin_unlock_bh(&priv->tx.tx_lock);
  228. if (len > sizeof(buf))
  229. len = sizeof(buf);
  230. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  231. }
  232. static const struct file_operations fops_slot = {
  233. .read = read_file_slot,
  234. .open = ath9k_debugfs_open,
  235. .owner = THIS_MODULE,
  236. .llseek = default_llseek,
  237. };
  238. static ssize_t read_file_queue(struct file *file, char __user *user_buf,
  239. size_t count, loff_t *ppos)
  240. {
  241. struct ath9k_htc_priv *priv = file->private_data;
  242. char buf[512];
  243. unsigned int len = 0;
  244. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  245. "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue));
  246. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  247. "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue));
  248. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  249. "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue));
  250. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  251. "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue));
  252. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  253. "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue));
  254. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  255. "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue));
  256. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  257. "Failed queue", skb_queue_len(&priv->tx.tx_failed));
  258. spin_lock_bh(&priv->tx.tx_lock);
  259. len += snprintf(buf + len, sizeof(buf) - len, "%16s : %3d\n",
  260. "Queued count", priv->tx.queued_cnt);
  261. spin_unlock_bh(&priv->tx.tx_lock);
  262. if (len > sizeof(buf))
  263. len = sizeof(buf);
  264. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  265. }
  266. static const struct file_operations fops_queue = {
  267. .read = read_file_queue,
  268. .open = ath9k_debugfs_open,
  269. .owner = THIS_MODULE,
  270. .llseek = default_llseek,
  271. };
  272. int ath9k_htc_init_debug(struct ath_hw *ah)
  273. {
  274. struct ath_common *common = ath9k_hw_common(ah);
  275. struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
  276. if (!ath9k_debugfs_root)
  277. return -ENOENT;
  278. priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy),
  279. ath9k_debugfs_root);
  280. if (!priv->debug.debugfs_phy)
  281. goto err;
  282. priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR,
  283. priv->debug.debugfs_phy,
  284. priv, &fops_tgt_stats);
  285. if (!priv->debug.debugfs_tgt_stats)
  286. goto err;
  287. priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR,
  288. priv->debug.debugfs_phy,
  289. priv, &fops_xmit);
  290. if (!priv->debug.debugfs_xmit)
  291. goto err;
  292. priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR,
  293. priv->debug.debugfs_phy,
  294. priv, &fops_recv);
  295. if (!priv->debug.debugfs_recv)
  296. goto err;
  297. priv->debug.debugfs_slot = debugfs_create_file("slot", S_IRUSR,
  298. priv->debug.debugfs_phy,
  299. priv, &fops_slot);
  300. if (!priv->debug.debugfs_slot)
  301. goto err;
  302. priv->debug.debugfs_queue = debugfs_create_file("queue", S_IRUSR,
  303. priv->debug.debugfs_phy,
  304. priv, &fops_queue);
  305. if (!priv->debug.debugfs_queue)
  306. goto err;
  307. return 0;
  308. err:
  309. ath9k_htc_exit_debug(ah);
  310. return -ENOMEM;
  311. }
  312. void ath9k_htc_exit_debug(struct ath_hw *ah)
  313. {
  314. struct ath_common *common = ath9k_hw_common(ah);
  315. struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
  316. debugfs_remove(priv->debug.debugfs_queue);
  317. debugfs_remove(priv->debug.debugfs_slot);
  318. debugfs_remove(priv->debug.debugfs_recv);
  319. debugfs_remove(priv->debug.debugfs_xmit);
  320. debugfs_remove(priv->debug.debugfs_tgt_stats);
  321. debugfs_remove(priv->debug.debugfs_phy);
  322. }
  323. int ath9k_htc_debug_create_root(void)
  324. {
  325. ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
  326. if (!ath9k_debugfs_root)
  327. return -ENOENT;
  328. return 0;
  329. }
  330. void ath9k_htc_debug_remove_root(void)
  331. {
  332. debugfs_remove(ath9k_debugfs_root);
  333. ath9k_debugfs_root = NULL;
  334. }