iwl-core.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 - 2012 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. * Intel Linux Wireless <ilw@linux.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/sched.h>
  31. #include <linux/slab.h>
  32. #include <net/mac80211.h>
  33. #include "iwl-eeprom.h"
  34. #include "iwl-debug.h"
  35. #include "iwl-core.h"
  36. #include "iwl-io.h"
  37. #include "iwl-power.h"
  38. #include "iwl-agn.h"
  39. #include "iwl-trans.h"
  40. #ifdef CONFIG_IWLWIFI_DEBUGFS
  41. #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
  42. void iwl_reset_traffic_log(struct iwl_priv *priv)
  43. {
  44. priv->tx_traffic_idx = 0;
  45. priv->rx_traffic_idx = 0;
  46. if (priv->tx_traffic)
  47. memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
  48. if (priv->rx_traffic)
  49. memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
  50. }
  51. int iwl_alloc_traffic_mem(struct iwl_priv *priv)
  52. {
  53. u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
  54. if (iwl_have_debug_level(IWL_DL_TX)) {
  55. if (!priv->tx_traffic) {
  56. priv->tx_traffic =
  57. kzalloc(traffic_size, GFP_KERNEL);
  58. if (!priv->tx_traffic)
  59. return -ENOMEM;
  60. }
  61. }
  62. if (iwl_have_debug_level(IWL_DL_RX)) {
  63. if (!priv->rx_traffic) {
  64. priv->rx_traffic =
  65. kzalloc(traffic_size, GFP_KERNEL);
  66. if (!priv->rx_traffic)
  67. return -ENOMEM;
  68. }
  69. }
  70. iwl_reset_traffic_log(priv);
  71. return 0;
  72. }
  73. void iwl_free_traffic_mem(struct iwl_priv *priv)
  74. {
  75. kfree(priv->tx_traffic);
  76. priv->tx_traffic = NULL;
  77. kfree(priv->rx_traffic);
  78. priv->rx_traffic = NULL;
  79. }
  80. void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
  81. u16 length, struct ieee80211_hdr *header)
  82. {
  83. __le16 fc;
  84. u16 len;
  85. if (likely(!iwl_have_debug_level(IWL_DL_TX)))
  86. return;
  87. if (!priv->tx_traffic)
  88. return;
  89. fc = header->frame_control;
  90. if (ieee80211_is_data(fc)) {
  91. len = (length > IWL_TRAFFIC_ENTRY_SIZE)
  92. ? IWL_TRAFFIC_ENTRY_SIZE : length;
  93. memcpy((priv->tx_traffic +
  94. (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
  95. header, len);
  96. priv->tx_traffic_idx =
  97. (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
  98. }
  99. }
  100. void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
  101. u16 length, struct ieee80211_hdr *header)
  102. {
  103. __le16 fc;
  104. u16 len;
  105. if (likely(!iwl_have_debug_level(IWL_DL_RX)))
  106. return;
  107. if (!priv->rx_traffic)
  108. return;
  109. fc = header->frame_control;
  110. if (ieee80211_is_data(fc)) {
  111. len = (length > IWL_TRAFFIC_ENTRY_SIZE)
  112. ? IWL_TRAFFIC_ENTRY_SIZE : length;
  113. memcpy((priv->rx_traffic +
  114. (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
  115. header, len);
  116. priv->rx_traffic_idx =
  117. (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
  118. }
  119. }
  120. const char *get_mgmt_string(int cmd)
  121. {
  122. #define IWL_CMD(x) case x: return #x
  123. switch (cmd) {
  124. IWL_CMD(MANAGEMENT_ASSOC_REQ);
  125. IWL_CMD(MANAGEMENT_ASSOC_RESP);
  126. IWL_CMD(MANAGEMENT_REASSOC_REQ);
  127. IWL_CMD(MANAGEMENT_REASSOC_RESP);
  128. IWL_CMD(MANAGEMENT_PROBE_REQ);
  129. IWL_CMD(MANAGEMENT_PROBE_RESP);
  130. IWL_CMD(MANAGEMENT_BEACON);
  131. IWL_CMD(MANAGEMENT_ATIM);
  132. IWL_CMD(MANAGEMENT_DISASSOC);
  133. IWL_CMD(MANAGEMENT_AUTH);
  134. IWL_CMD(MANAGEMENT_DEAUTH);
  135. IWL_CMD(MANAGEMENT_ACTION);
  136. default:
  137. return "UNKNOWN";
  138. }
  139. #undef IWL_CMD
  140. }
  141. const char *get_ctrl_string(int cmd)
  142. {
  143. #define IWL_CMD(x) case x: return #x
  144. switch (cmd) {
  145. IWL_CMD(CONTROL_BACK_REQ);
  146. IWL_CMD(CONTROL_BACK);
  147. IWL_CMD(CONTROL_PSPOLL);
  148. IWL_CMD(CONTROL_RTS);
  149. IWL_CMD(CONTROL_CTS);
  150. IWL_CMD(CONTROL_ACK);
  151. IWL_CMD(CONTROL_CFEND);
  152. IWL_CMD(CONTROL_CFENDACK);
  153. default:
  154. return "UNKNOWN";
  155. }
  156. #undef IWL_CMD
  157. }
  158. void iwl_clear_traffic_stats(struct iwl_priv *priv)
  159. {
  160. memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
  161. memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
  162. }
  163. /*
  164. * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will
  165. * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass.
  166. * Use debugFs to display the rx/rx_statistics
  167. * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL
  168. * information will be recorded, but DATA pkt still will be recorded
  169. * for the reason of iwl_led.c need to control the led blinking based on
  170. * number of tx and rx data.
  171. *
  172. */
  173. void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
  174. {
  175. struct traffic_stats *stats;
  176. if (is_tx)
  177. stats = &priv->tx_stats;
  178. else
  179. stats = &priv->rx_stats;
  180. if (ieee80211_is_mgmt(fc)) {
  181. switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  182. case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
  183. stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
  184. break;
  185. case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
  186. stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
  187. break;
  188. case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
  189. stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
  190. break;
  191. case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
  192. stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
  193. break;
  194. case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
  195. stats->mgmt[MANAGEMENT_PROBE_REQ]++;
  196. break;
  197. case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
  198. stats->mgmt[MANAGEMENT_PROBE_RESP]++;
  199. break;
  200. case cpu_to_le16(IEEE80211_STYPE_BEACON):
  201. stats->mgmt[MANAGEMENT_BEACON]++;
  202. break;
  203. case cpu_to_le16(IEEE80211_STYPE_ATIM):
  204. stats->mgmt[MANAGEMENT_ATIM]++;
  205. break;
  206. case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
  207. stats->mgmt[MANAGEMENT_DISASSOC]++;
  208. break;
  209. case cpu_to_le16(IEEE80211_STYPE_AUTH):
  210. stats->mgmt[MANAGEMENT_AUTH]++;
  211. break;
  212. case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
  213. stats->mgmt[MANAGEMENT_DEAUTH]++;
  214. break;
  215. case cpu_to_le16(IEEE80211_STYPE_ACTION):
  216. stats->mgmt[MANAGEMENT_ACTION]++;
  217. break;
  218. }
  219. } else if (ieee80211_is_ctl(fc)) {
  220. switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  221. case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
  222. stats->ctrl[CONTROL_BACK_REQ]++;
  223. break;
  224. case cpu_to_le16(IEEE80211_STYPE_BACK):
  225. stats->ctrl[CONTROL_BACK]++;
  226. break;
  227. case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
  228. stats->ctrl[CONTROL_PSPOLL]++;
  229. break;
  230. case cpu_to_le16(IEEE80211_STYPE_RTS):
  231. stats->ctrl[CONTROL_RTS]++;
  232. break;
  233. case cpu_to_le16(IEEE80211_STYPE_CTS):
  234. stats->ctrl[CONTROL_CTS]++;
  235. break;
  236. case cpu_to_le16(IEEE80211_STYPE_ACK):
  237. stats->ctrl[CONTROL_ACK]++;
  238. break;
  239. case cpu_to_le16(IEEE80211_STYPE_CFEND):
  240. stats->ctrl[CONTROL_CFEND]++;
  241. break;
  242. case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
  243. stats->ctrl[CONTROL_CFENDACK]++;
  244. break;
  245. }
  246. } else {
  247. /* data */
  248. stats->data_cnt++;
  249. stats->data_bytes += len;
  250. }
  251. }
  252. #endif
  253. int iwl_cmd_echo_test(struct iwl_priv *priv)
  254. {
  255. int ret;
  256. struct iwl_host_cmd cmd = {
  257. .id = REPLY_ECHO,
  258. .len = { 0 },
  259. .flags = CMD_SYNC,
  260. };
  261. ret = iwl_dvm_send_cmd(priv, &cmd);
  262. if (ret)
  263. IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
  264. else
  265. IWL_DEBUG_INFO(priv, "echo testing pass\n");
  266. return ret;
  267. }