1 /******************************************************************************
5 * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
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.
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.
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,
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
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 *****************************************************************************/
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/sched.h>
32 #include <linux/slab.h>
33 #include <net/mac80211.h>
35 #include "iwl-eeprom.h"
36 #include "iwl-debug.h"
39 #include "iwl-power.h"
40 #include "iwl-shared.h"
42 #include "iwl-trans.h"
44 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
48 #ifdef CONFIG_IWLWIFI_DEBUGFS
50 #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
52 void iwl_reset_traffic_log(struct iwl_priv *priv)
54 priv->tx_traffic_idx = 0;
55 priv->rx_traffic_idx = 0;
57 memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
59 memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
62 int iwl_alloc_traffic_mem(struct iwl_priv *priv)
64 u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
66 if (iwl_have_debug_level(IWL_DL_TX)) {
67 if (!priv->tx_traffic) {
69 kzalloc(traffic_size, GFP_KERNEL);
70 if (!priv->tx_traffic)
74 if (iwl_have_debug_level(IWL_DL_RX)) {
75 if (!priv->rx_traffic) {
77 kzalloc(traffic_size, GFP_KERNEL);
78 if (!priv->rx_traffic)
82 iwl_reset_traffic_log(priv);
86 void iwl_free_traffic_mem(struct iwl_priv *priv)
88 kfree(priv->tx_traffic);
89 priv->tx_traffic = NULL;
91 kfree(priv->rx_traffic);
92 priv->rx_traffic = NULL;
95 void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
96 u16 length, struct ieee80211_hdr *header)
101 if (likely(!iwl_have_debug_level(IWL_DL_TX)))
104 if (!priv->tx_traffic)
107 fc = header->frame_control;
108 if (ieee80211_is_data(fc)) {
109 len = (length > IWL_TRAFFIC_ENTRY_SIZE)
110 ? IWL_TRAFFIC_ENTRY_SIZE : length;
111 memcpy((priv->tx_traffic +
112 (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
114 priv->tx_traffic_idx =
115 (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
119 void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
120 u16 length, struct ieee80211_hdr *header)
125 if (likely(!iwl_have_debug_level(IWL_DL_RX)))
128 if (!priv->rx_traffic)
131 fc = header->frame_control;
132 if (ieee80211_is_data(fc)) {
133 len = (length > IWL_TRAFFIC_ENTRY_SIZE)
134 ? IWL_TRAFFIC_ENTRY_SIZE : length;
135 memcpy((priv->rx_traffic +
136 (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
138 priv->rx_traffic_idx =
139 (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
143 const char *get_mgmt_string(int cmd)
146 IWL_CMD(MANAGEMENT_ASSOC_REQ);
147 IWL_CMD(MANAGEMENT_ASSOC_RESP);
148 IWL_CMD(MANAGEMENT_REASSOC_REQ);
149 IWL_CMD(MANAGEMENT_REASSOC_RESP);
150 IWL_CMD(MANAGEMENT_PROBE_REQ);
151 IWL_CMD(MANAGEMENT_PROBE_RESP);
152 IWL_CMD(MANAGEMENT_BEACON);
153 IWL_CMD(MANAGEMENT_ATIM);
154 IWL_CMD(MANAGEMENT_DISASSOC);
155 IWL_CMD(MANAGEMENT_AUTH);
156 IWL_CMD(MANAGEMENT_DEAUTH);
157 IWL_CMD(MANAGEMENT_ACTION);
164 const char *get_ctrl_string(int cmd)
167 IWL_CMD(CONTROL_BACK_REQ);
168 IWL_CMD(CONTROL_BACK);
169 IWL_CMD(CONTROL_PSPOLL);
170 IWL_CMD(CONTROL_RTS);
171 IWL_CMD(CONTROL_CTS);
172 IWL_CMD(CONTROL_ACK);
173 IWL_CMD(CONTROL_CFEND);
174 IWL_CMD(CONTROL_CFENDACK);
181 void iwl_clear_traffic_stats(struct iwl_priv *priv)
183 memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
184 memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
188 * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will
189 * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass.
190 * Use debugFs to display the rx/rx_statistics
191 * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL
192 * information will be recorded, but DATA pkt still will be recorded
193 * for the reason of iwl_led.c need to control the led blinking based on
194 * number of tx and rx data.
197 void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
199 struct traffic_stats *stats;
202 stats = &priv->tx_stats;
204 stats = &priv->rx_stats;
206 if (ieee80211_is_mgmt(fc)) {
207 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
208 case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
209 stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
211 case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
212 stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
214 case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
215 stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
217 case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
218 stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
220 case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
221 stats->mgmt[MANAGEMENT_PROBE_REQ]++;
223 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
224 stats->mgmt[MANAGEMENT_PROBE_RESP]++;
226 case cpu_to_le16(IEEE80211_STYPE_BEACON):
227 stats->mgmt[MANAGEMENT_BEACON]++;
229 case cpu_to_le16(IEEE80211_STYPE_ATIM):
230 stats->mgmt[MANAGEMENT_ATIM]++;
232 case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
233 stats->mgmt[MANAGEMENT_DISASSOC]++;
235 case cpu_to_le16(IEEE80211_STYPE_AUTH):
236 stats->mgmt[MANAGEMENT_AUTH]++;
238 case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
239 stats->mgmt[MANAGEMENT_DEAUTH]++;
241 case cpu_to_le16(IEEE80211_STYPE_ACTION):
242 stats->mgmt[MANAGEMENT_ACTION]++;
245 } else if (ieee80211_is_ctl(fc)) {
246 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
247 case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
248 stats->ctrl[CONTROL_BACK_REQ]++;
250 case cpu_to_le16(IEEE80211_STYPE_BACK):
251 stats->ctrl[CONTROL_BACK]++;
253 case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
254 stats->ctrl[CONTROL_PSPOLL]++;
256 case cpu_to_le16(IEEE80211_STYPE_RTS):
257 stats->ctrl[CONTROL_RTS]++;
259 case cpu_to_le16(IEEE80211_STYPE_CTS):
260 stats->ctrl[CONTROL_CTS]++;
262 case cpu_to_le16(IEEE80211_STYPE_ACK):
263 stats->ctrl[CONTROL_ACK]++;
265 case cpu_to_le16(IEEE80211_STYPE_CFEND):
266 stats->ctrl[CONTROL_CFEND]++;
268 case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
269 stats->ctrl[CONTROL_CFENDACK]++;
275 stats->data_bytes += len;
280 int iwl_cmd_echo_test(struct iwl_priv *priv)
283 struct iwl_host_cmd cmd = {
289 ret = iwl_dvm_send_cmd(priv, &cmd);
291 IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
293 IWL_DEBUG_INFO(priv, "echo testing pass\n");