iwl-core.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. 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. }
  140. const char *get_ctrl_string(int cmd)
  141. {
  142. switch (cmd) {
  143. IWL_CMD(CONTROL_BACK_REQ);
  144. IWL_CMD(CONTROL_BACK);
  145. IWL_CMD(CONTROL_PSPOLL);
  146. IWL_CMD(CONTROL_RTS);
  147. IWL_CMD(CONTROL_CTS);
  148. IWL_CMD(CONTROL_ACK);
  149. IWL_CMD(CONTROL_CFEND);
  150. IWL_CMD(CONTROL_CFENDACK);
  151. default:
  152. return "UNKNOWN";
  153. }
  154. }
  155. void iwl_clear_traffic_stats(struct iwl_priv *priv)
  156. {
  157. memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
  158. memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
  159. }
  160. /*
  161. * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will
  162. * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass.
  163. * Use debugFs to display the rx/rx_statistics
  164. * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL
  165. * information will be recorded, but DATA pkt still will be recorded
  166. * for the reason of iwl_led.c need to control the led blinking based on
  167. * number of tx and rx data.
  168. *
  169. */
  170. void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
  171. {
  172. struct traffic_stats *stats;
  173. if (is_tx)
  174. stats = &priv->tx_stats;
  175. else
  176. stats = &priv->rx_stats;
  177. if (ieee80211_is_mgmt(fc)) {
  178. switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  179. case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
  180. stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
  181. break;
  182. case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
  183. stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
  184. break;
  185. case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
  186. stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
  187. break;
  188. case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
  189. stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
  190. break;
  191. case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
  192. stats->mgmt[MANAGEMENT_PROBE_REQ]++;
  193. break;
  194. case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
  195. stats->mgmt[MANAGEMENT_PROBE_RESP]++;
  196. break;
  197. case cpu_to_le16(IEEE80211_STYPE_BEACON):
  198. stats->mgmt[MANAGEMENT_BEACON]++;
  199. break;
  200. case cpu_to_le16(IEEE80211_STYPE_ATIM):
  201. stats->mgmt[MANAGEMENT_ATIM]++;
  202. break;
  203. case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
  204. stats->mgmt[MANAGEMENT_DISASSOC]++;
  205. break;
  206. case cpu_to_le16(IEEE80211_STYPE_AUTH):
  207. stats->mgmt[MANAGEMENT_AUTH]++;
  208. break;
  209. case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
  210. stats->mgmt[MANAGEMENT_DEAUTH]++;
  211. break;
  212. case cpu_to_le16(IEEE80211_STYPE_ACTION):
  213. stats->mgmt[MANAGEMENT_ACTION]++;
  214. break;
  215. }
  216. } else if (ieee80211_is_ctl(fc)) {
  217. switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
  218. case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
  219. stats->ctrl[CONTROL_BACK_REQ]++;
  220. break;
  221. case cpu_to_le16(IEEE80211_STYPE_BACK):
  222. stats->ctrl[CONTROL_BACK]++;
  223. break;
  224. case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
  225. stats->ctrl[CONTROL_PSPOLL]++;
  226. break;
  227. case cpu_to_le16(IEEE80211_STYPE_RTS):
  228. stats->ctrl[CONTROL_RTS]++;
  229. break;
  230. case cpu_to_le16(IEEE80211_STYPE_CTS):
  231. stats->ctrl[CONTROL_CTS]++;
  232. break;
  233. case cpu_to_le16(IEEE80211_STYPE_ACK):
  234. stats->ctrl[CONTROL_ACK]++;
  235. break;
  236. case cpu_to_le16(IEEE80211_STYPE_CFEND):
  237. stats->ctrl[CONTROL_CFEND]++;
  238. break;
  239. case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
  240. stats->ctrl[CONTROL_CFENDACK]++;
  241. break;
  242. }
  243. } else {
  244. /* data */
  245. stats->data_cnt++;
  246. stats->data_bytes += len;
  247. }
  248. }
  249. #endif
  250. int iwl_cmd_echo_test(struct iwl_priv *priv)
  251. {
  252. int ret;
  253. struct iwl_host_cmd cmd = {
  254. .id = REPLY_ECHO,
  255. .len = { 0 },
  256. .flags = CMD_SYNC,
  257. };
  258. ret = iwl_dvm_send_cmd(priv, &cmd);
  259. if (ret)
  260. IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
  261. else
  262. IWL_DEBUG_INFO(priv, "echo testing pass\n");
  263. return ret;
  264. }