Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sta_event.c
Go to the documentation of this file.
1 /*
2  * Marvell Wireless LAN device driver: station event handling
3  *
4  * Copyright (C) 2011, Marvell International Ltd.
5  *
6  * This software file (the "File") is distributed by Marvell International
7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8  * (the "License"). You may use, redistribute and/or modify this File in
9  * accordance with the terms and conditions of the License, a copy of which
10  * is available by writing to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13  *
14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16  * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17  * this warranty disclaimer.
18  */
19 
20 #include "decl.h"
21 #include "ioctl.h"
22 #include "util.h"
23 #include "fw.h"
24 #include "main.h"
25 #include "wmm.h"
26 #include "11n.h"
27 
28 /*
29  * This function resets the connection state.
30  *
31  * The function is invoked after receiving a disconnect event from firmware,
32  * and performs the following actions -
33  * - Set media status to disconnected
34  * - Clean up Tx and Rx packets
35  * - Resets SNR/NF/RSSI value in driver
36  * - Resets security configurations in driver
37  * - Enables auto data rate
38  * - Saves the previous SSID and BSSID so that they can
39  * be used for re-association, if required
40  * - Erases current SSID and BSSID information
41  * - Sends a disconnect event to upper layers/applications.
42  */
43 void
45 {
46  struct mwifiex_adapter *adapter = priv->adapter;
47 
48  if (!priv->media_connected)
49  return;
50 
51  dev_dbg(adapter->dev, "info: handles disconnect event\n");
52 
53  priv->media_connected = false;
54 
55  priv->scan_block = false;
56 
57  /* Free Tx and Rx packets, report disconnect to upper layer */
58  mwifiex_clean_txrx(priv);
59 
60  /* Reset SNR/NF/RSSI values */
61  priv->data_rssi_last = 0;
62  priv->data_nf_last = 0;
63  priv->data_rssi_avg = 0;
64  priv->data_nf_avg = 0;
65  priv->bcn_rssi_last = 0;
66  priv->bcn_nf_last = 0;
67  priv->bcn_rssi_avg = 0;
68  priv->bcn_nf_avg = 0;
69  priv->rxpd_rate = 0;
70  priv->rxpd_htinfo = 0;
71  priv->sec_info.wpa_enabled = false;
72  priv->sec_info.wpa2_enabled = false;
73  priv->wpa_ie_len = 0;
74 
75  priv->sec_info.wapi_enabled = false;
76  priv->wapi_ie_len = 0;
77  priv->sec_info.wapi_key_on = false;
78 
79  priv->sec_info.encryption_mode = 0;
80 
81  /* Enable auto data rate */
82  priv->is_data_rate_auto = true;
83  priv->data_rate = 0;
84 
85  if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
86  priv->adhoc_state = ADHOC_IDLE;
87  priv->adhoc_is_link_sensed = false;
88  }
89 
90  /*
91  * Memorize the previous SSID and BSSID so
92  * it could be used for re-assoc
93  */
94 
95  dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n",
96  priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
97 
98  dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n",
99  priv->curr_bss_params.bss_descriptor.ssid.ssid,
100  priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
101 
102  memcpy(&priv->prev_ssid,
103  &priv->curr_bss_params.bss_descriptor.ssid,
104  sizeof(struct cfg80211_ssid));
105 
106  memcpy(priv->prev_bssid,
107  priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);
108 
109  /* Need to erase the current SSID and BSSID info */
110  memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));
111 
112  adapter->tx_lock_flag = false;
113  adapter->pps_uapsd_mode = false;
114 
115  if (adapter->num_cmd_timeout && adapter->curr_cmd)
116  return;
117  priv->media_connected = false;
118  dev_dbg(adapter->dev,
119  "info: successfully disconnected from %pM: reason code %d\n",
120  priv->cfg_bssid, reason_code);
121  if (priv->bss_mode == NL80211_IFTYPE_STATION) {
122  cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
123  GFP_KERNEL);
124  }
125  memset(priv->cfg_bssid, 0, ETH_ALEN);
126 
127  if (!netif_queue_stopped(priv->netdev))
128  mwifiex_stop_net_dev_queue(priv->netdev, adapter);
129  if (netif_carrier_ok(priv->netdev))
130  netif_carrier_off(priv->netdev);
131 }
132 
133 /*
134  * This function handles events generated by firmware.
135  *
136  * This is a generic function and handles all events.
137  *
138  * Event specific routines are called by this function based
139  * upon the generated event cause.
140  *
141  * For the following events, the function just forwards them to upper
142  * layers, optionally recording the change -
143  * - EVENT_LINK_SENSED
144  * - EVENT_MIC_ERR_UNICAST
145  * - EVENT_MIC_ERR_MULTICAST
146  * - EVENT_PORT_RELEASE
147  * - EVENT_RSSI_LOW
148  * - EVENT_SNR_LOW
149  * - EVENT_MAX_FAIL
150  * - EVENT_RSSI_HIGH
151  * - EVENT_SNR_HIGH
152  * - EVENT_DATA_RSSI_LOW
153  * - EVENT_DATA_SNR_LOW
154  * - EVENT_DATA_RSSI_HIGH
155  * - EVENT_DATA_SNR_HIGH
156  * - EVENT_LINK_QUALITY
157  * - EVENT_PRE_BEACON_LOST
158  * - EVENT_IBSS_COALESCED
159  * - EVENT_WEP_ICV_ERR
160  * - EVENT_BW_CHANGE
161  * - EVENT_HOSTWAKE_STAIE
162  *
163  * For the following events, no action is taken -
164  * - EVENT_MIB_CHANGED
165  * - EVENT_INIT_DONE
166  * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL
167  *
168  * Rest of the supported events requires driver handling -
169  * - EVENT_DEAUTHENTICATED
170  * - EVENT_DISASSOCIATED
171  * - EVENT_LINK_LOST
172  * - EVENT_PS_SLEEP
173  * - EVENT_PS_AWAKE
174  * - EVENT_DEEP_SLEEP_AWAKE
175  * - EVENT_HS_ACT_REQ
176  * - EVENT_ADHOC_BCN_LOST
177  * - EVENT_BG_SCAN_REPORT
178  * - EVENT_WMM_STATUS_CHANGE
179  * - EVENT_ADDBA
180  * - EVENT_DELBA
181  * - EVENT_BA_STREAM_TIEMOUT
182  * - EVENT_AMSDU_AGGR_CTRL
183  */
185 {
186  struct mwifiex_adapter *adapter = priv->adapter;
187  int ret = 0;
188  u32 eventcause = adapter->event_cause;
190 
191  switch (eventcause) {
193  dev_err(adapter->dev,
194  "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
195  break;
196  case EVENT_LINK_SENSED:
197  dev_dbg(adapter->dev, "event: LINK_SENSED\n");
198  if (!netif_carrier_ok(priv->netdev))
199  netif_carrier_on(priv->netdev);
200  if (netif_queue_stopped(priv->netdev))
201  mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
202  break;
203 
205  dev_dbg(adapter->dev, "event: Deauthenticated\n");
206  adapter->dbg.num_event_deauth++;
207  if (priv->media_connected) {
208  reason_code =
209  le16_to_cpu(*(__le16 *)adapter->event_body);
210  mwifiex_reset_connect_state(priv, reason_code);
211  }
212  break;
213 
214  case EVENT_DISASSOCIATED:
215  dev_dbg(adapter->dev, "event: Disassociated\n");
216  adapter->dbg.num_event_disassoc++;
217  if (priv->media_connected) {
218  reason_code =
219  le16_to_cpu(*(__le16 *)adapter->event_body);
220  mwifiex_reset_connect_state(priv, reason_code);
221  }
222  break;
223 
224  case EVENT_LINK_LOST:
225  dev_dbg(adapter->dev, "event: Link lost\n");
226  adapter->dbg.num_event_link_lost++;
227  if (priv->media_connected) {
228  reason_code =
229  le16_to_cpu(*(__le16 *)adapter->event_body);
230  mwifiex_reset_connect_state(priv, reason_code);
231  }
232  break;
233 
234  case EVENT_PS_SLEEP:
235  dev_dbg(adapter->dev, "info: EVENT: SLEEP\n");
236 
237  adapter->ps_state = PS_STATE_PRE_SLEEP;
238 
239  mwifiex_check_ps_cond(adapter);
240  break;
241 
242  case EVENT_PS_AWAKE:
243  dev_dbg(adapter->dev, "info: EVENT: AWAKE\n");
244  if (!adapter->pps_uapsd_mode &&
245  priv->media_connected && adapter->sleep_period.period) {
246  adapter->pps_uapsd_mode = true;
247  dev_dbg(adapter->dev,
248  "event: PPS/UAPSD mode activated\n");
249  }
250  adapter->tx_lock_flag = false;
251  if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
253  if (adapter->data_sent) {
254  adapter->ps_state = PS_STATE_AWAKE;
255  adapter->pm_wakeup_card_req = false;
256  adapter->pm_wakeup_fw_try = false;
257  break;
258  }
260  (priv,
263  adapter->ps_state =
265  return 0;
266  }
267  }
268  adapter->ps_state = PS_STATE_AWAKE;
269  adapter->pm_wakeup_card_req = false;
270  adapter->pm_wakeup_fw_try = false;
271 
272  break;
273 
275  adapter->if_ops.wakeup_complete(adapter);
276  dev_dbg(adapter->dev, "event: DS_AWAKE\n");
277  if (adapter->is_deep_sleep)
278  adapter->is_deep_sleep = false;
279  break;
280 
281  case EVENT_HS_ACT_REQ:
282  dev_dbg(adapter->dev, "event: HS_ACT_REQ\n");
283  ret = mwifiex_send_cmd_async(priv,
285  0, 0, NULL);
286  break;
287 
289  dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n");
292  -1, NULL, GFP_KERNEL);
293  break;
294 
296  dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n");
299  -1, NULL, GFP_KERNEL);
300  break;
301  case EVENT_MIB_CHANGED:
302  case EVENT_INIT_DONE:
303  break;
304 
306  dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n");
307  priv->adhoc_is_link_sensed = false;
308  mwifiex_clean_txrx(priv);
309  if (!netif_queue_stopped(priv->netdev))
310  mwifiex_stop_net_dev_queue(priv->netdev, adapter);
311  if (netif_carrier_ok(priv->netdev))
312  netif_carrier_off(priv->netdev);
313  break;
314 
316  dev_dbg(adapter->dev, "event: BGS_REPORT\n");
317  ret = mwifiex_send_cmd_async(priv,
320  break;
321 
322  case EVENT_PORT_RELEASE:
323  dev_dbg(adapter->dev, "event: PORT RELEASE\n");
324  break;
325 
327  dev_dbg(adapter->dev, "event: WMM status changed\n");
329  0, 0, NULL);
330  break;
331 
332  case EVENT_RSSI_LOW:
335  GFP_KERNEL);
339  dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n");
340  break;
341  case EVENT_SNR_LOW:
342  dev_dbg(adapter->dev, "event: Beacon SNR_LOW\n");
343  break;
344  case EVENT_MAX_FAIL:
345  dev_dbg(adapter->dev, "event: MAX_FAIL\n");
346  break;
347  case EVENT_RSSI_HIGH:
350  GFP_KERNEL);
354  dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n");
355  break;
356  case EVENT_SNR_HIGH:
357  dev_dbg(adapter->dev, "event: Beacon SNR_HIGH\n");
358  break;
359  case EVENT_DATA_RSSI_LOW:
360  dev_dbg(adapter->dev, "event: Data RSSI_LOW\n");
361  break;
362  case EVENT_DATA_SNR_LOW:
363  dev_dbg(adapter->dev, "event: Data SNR_LOW\n");
364  break;
366  dev_dbg(adapter->dev, "event: Data RSSI_HIGH\n");
367  break;
368  case EVENT_DATA_SNR_HIGH:
369  dev_dbg(adapter->dev, "event: Data SNR_HIGH\n");
370  break;
371  case EVENT_LINK_QUALITY:
372  dev_dbg(adapter->dev, "event: Link Quality\n");
373  break;
375  dev_dbg(adapter->dev, "event: Pre-Beacon Lost\n");
376  break;
378  dev_dbg(adapter->dev, "event: IBSS_COALESCED\n");
379  ret = mwifiex_send_cmd_async(priv,
382  break;
383  case EVENT_ADDBA:
384  dev_dbg(adapter->dev, "event: ADDBA Request\n");
387  adapter->event_body);
388  break;
389  case EVENT_DELBA:
390  dev_dbg(adapter->dev, "event: DELBA Request\n");
392  break;
394  dev_dbg(adapter->dev, "event: BA Stream timeout\n");
397  *)
398  adapter->event_body);
399  break;
401  ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
402  dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);
403 
404  adapter->tx_buf_size =
405  min_t(u16, adapter->curr_tx_buf_size, ctrl);
406  dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
407  adapter->tx_buf_size);
408  break;
409 
410  case EVENT_WEP_ICV_ERR:
411  dev_dbg(adapter->dev, "event: WEP ICV error\n");
412  break;
413 
414  case EVENT_BW_CHANGE:
415  dev_dbg(adapter->dev, "event: BW Change\n");
416  break;
417 
419  dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
420  break;
421 
423  dev_dbg(adapter->dev, "event: Remain on channel expired\n");
425  priv->roc_cfg.cookie,
426  &priv->roc_cfg.chan,
427  priv->roc_cfg.chan_type,
428  GFP_ATOMIC);
429 
430  memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
431 
432  break;
433 
434  default:
435  dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
436  eventcause);
437  break;
438  }
439 
440  return ret;
441 }