iwlwifi: move iwl_force_rf_reset to iwl-agn-rx.c
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / net / wireless / iwlwifi / iwl-core.c
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
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>
34
35 #include "iwl-eeprom.h"
36 #include "iwl-debug.h"
37 #include "iwl-core.h"
38 #include "iwl-io.h"
39 #include "iwl-power.h"
40 #include "iwl-shared.h"
41 #include "iwl-agn.h"
42 #include "iwl-trans.h"
43
44 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
45
46
47
48 #ifdef CONFIG_IWLWIFI_DEBUGFS
49
50 #define IWL_TRAFFIC_DUMP_SIZE   (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
51
52 void iwl_reset_traffic_log(struct iwl_priv *priv)
53 {
54         priv->tx_traffic_idx = 0;
55         priv->rx_traffic_idx = 0;
56         if (priv->tx_traffic)
57                 memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
58         if (priv->rx_traffic)
59                 memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
60 }
61
62 int iwl_alloc_traffic_mem(struct iwl_priv *priv)
63 {
64         u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
65
66         if (iwl_have_debug_level(IWL_DL_TX)) {
67                 if (!priv->tx_traffic) {
68                         priv->tx_traffic =
69                                 kzalloc(traffic_size, GFP_KERNEL);
70                         if (!priv->tx_traffic)
71                                 return -ENOMEM;
72                 }
73         }
74         if (iwl_have_debug_level(IWL_DL_RX)) {
75                 if (!priv->rx_traffic) {
76                         priv->rx_traffic =
77                                 kzalloc(traffic_size, GFP_KERNEL);
78                         if (!priv->rx_traffic)
79                                 return -ENOMEM;
80                 }
81         }
82         iwl_reset_traffic_log(priv);
83         return 0;
84 }
85
86 void iwl_free_traffic_mem(struct iwl_priv *priv)
87 {
88         kfree(priv->tx_traffic);
89         priv->tx_traffic = NULL;
90
91         kfree(priv->rx_traffic);
92         priv->rx_traffic = NULL;
93 }
94
95 void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
96                       u16 length, struct ieee80211_hdr *header)
97 {
98         __le16 fc;
99         u16 len;
100
101         if (likely(!iwl_have_debug_level(IWL_DL_TX)))
102                 return;
103
104         if (!priv->tx_traffic)
105                 return;
106
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)),
113                        header, len);
114                 priv->tx_traffic_idx =
115                         (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
116         }
117 }
118
119 void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
120                       u16 length, struct ieee80211_hdr *header)
121 {
122         __le16 fc;
123         u16 len;
124
125         if (likely(!iwl_have_debug_level(IWL_DL_RX)))
126                 return;
127
128         if (!priv->rx_traffic)
129                 return;
130
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)),
137                        header, len);
138                 priv->rx_traffic_idx =
139                         (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
140         }
141 }
142
143 const char *get_mgmt_string(int cmd)
144 {
145         switch (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);
158         default:
159                 return "UNKNOWN";
160
161         }
162 }
163
164 const char *get_ctrl_string(int cmd)
165 {
166         switch (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);
175         default:
176                 return "UNKNOWN";
177
178         }
179 }
180
181 void iwl_clear_traffic_stats(struct iwl_priv *priv)
182 {
183         memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
184         memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
185 }
186
187 /*
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.
195  *
196  */
197 void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
198 {
199         struct traffic_stats    *stats;
200
201         if (is_tx)
202                 stats = &priv->tx_stats;
203         else
204                 stats = &priv->rx_stats;
205
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]++;
210                         break;
211                 case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
212                         stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
213                         break;
214                 case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
215                         stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
216                         break;
217                 case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
218                         stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
219                         break;
220                 case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
221                         stats->mgmt[MANAGEMENT_PROBE_REQ]++;
222                         break;
223                 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
224                         stats->mgmt[MANAGEMENT_PROBE_RESP]++;
225                         break;
226                 case cpu_to_le16(IEEE80211_STYPE_BEACON):
227                         stats->mgmt[MANAGEMENT_BEACON]++;
228                         break;
229                 case cpu_to_le16(IEEE80211_STYPE_ATIM):
230                         stats->mgmt[MANAGEMENT_ATIM]++;
231                         break;
232                 case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
233                         stats->mgmt[MANAGEMENT_DISASSOC]++;
234                         break;
235                 case cpu_to_le16(IEEE80211_STYPE_AUTH):
236                         stats->mgmt[MANAGEMENT_AUTH]++;
237                         break;
238                 case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
239                         stats->mgmt[MANAGEMENT_DEAUTH]++;
240                         break;
241                 case cpu_to_le16(IEEE80211_STYPE_ACTION):
242                         stats->mgmt[MANAGEMENT_ACTION]++;
243                         break;
244                 }
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]++;
249                         break;
250                 case cpu_to_le16(IEEE80211_STYPE_BACK):
251                         stats->ctrl[CONTROL_BACK]++;
252                         break;
253                 case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
254                         stats->ctrl[CONTROL_PSPOLL]++;
255                         break;
256                 case cpu_to_le16(IEEE80211_STYPE_RTS):
257                         stats->ctrl[CONTROL_RTS]++;
258                         break;
259                 case cpu_to_le16(IEEE80211_STYPE_CTS):
260                         stats->ctrl[CONTROL_CTS]++;
261                         break;
262                 case cpu_to_le16(IEEE80211_STYPE_ACK):
263                         stats->ctrl[CONTROL_ACK]++;
264                         break;
265                 case cpu_to_le16(IEEE80211_STYPE_CFEND):
266                         stats->ctrl[CONTROL_CFEND]++;
267                         break;
268                 case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
269                         stats->ctrl[CONTROL_CFENDACK]++;
270                         break;
271                 }
272         } else {
273                 /* data */
274                 stats->data_cnt++;
275                 stats->data_bytes += len;
276         }
277 }
278 #endif
279
280 int iwl_cmd_echo_test(struct iwl_priv *priv)
281 {
282         int ret;
283         struct iwl_host_cmd cmd = {
284                 .id = REPLY_ECHO,
285                 .len = { 0 },
286                 .flags = CMD_SYNC,
287         };
288
289         ret = iwl_dvm_send_cmd(priv, &cmd);
290         if (ret)
291                 IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
292         else
293                 IWL_DEBUG_INFO(priv, "echo testing pass\n");
294         return ret;
295 }