iwl-core.c 7.5 KB

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