iwl-core.c 7.5 KB

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