2 * NXP Wireless LAN device driver: station event handling
4 * Copyright 2011-2020 NXP
6 * This software file (the "File") is distributed by NXP
7 * 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.
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.
28 #define MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE 12
30 static int mwifiex_check_ibss_peer_capabilities(struct mwifiex_private
*priv
,
31 struct mwifiex_sta_node
*sta_ptr
,
32 struct sk_buff
*event
)
36 struct ieee_types_header
*ele_hdr
;
37 struct mwifiex_ie_types_mgmt_frame
*tlv_mgmt_frame
;
38 const struct ieee80211_ht_cap
*ht_cap
;
39 const struct ieee80211_vht_cap
*vht_cap
;
41 skb_pull(event
, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE
);
45 mwifiex_dbg_dump(priv
->adapter
, EVT_D
, "ibss peer capabilities:",
46 event
->data
, event
->len
);
48 skb_push(event
, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE
);
50 tlv_mgmt_frame
= (void *)curr
;
51 if (evt_len
>= sizeof(*tlv_mgmt_frame
) &&
52 le16_to_cpu(tlv_mgmt_frame
->header
.type
) ==
53 TLV_TYPE_UAP_MGMT_FRAME
) {
54 /* Locate curr pointer to the start of beacon tlv,
55 * timestamp 8 bytes, beacon intervel 2 bytes,
56 * capability info 2 bytes, totally 12 byte beacon header
58 evt_len
= le16_to_cpu(tlv_mgmt_frame
->header
.len
);
59 curr
+= (sizeof(*tlv_mgmt_frame
) + 12);
61 mwifiex_dbg(priv
->adapter
, MSG
,
62 "management frame tlv not found!\n");
66 while (evt_len
>= sizeof(*ele_hdr
)) {
67 ele_hdr
= (struct ieee_types_header
*)curr
;
68 ele_len
= ele_hdr
->len
;
70 if (evt_len
< ele_len
+ sizeof(*ele_hdr
))
73 switch (ele_hdr
->element_id
) {
74 case WLAN_EID_HT_CAPABILITY
:
75 sta_ptr
->is_11n_enabled
= true;
76 ht_cap
= (void *)(ele_hdr
+ 2);
77 sta_ptr
->max_amsdu
= le16_to_cpu(ht_cap
->cap_info
) &
78 IEEE80211_HT_CAP_MAX_AMSDU
?
79 MWIFIEX_TX_DATA_BUF_SIZE_8K
:
80 MWIFIEX_TX_DATA_BUF_SIZE_4K
;
81 mwifiex_dbg(priv
->adapter
, INFO
,
82 "11n enabled!, max_amsdu : %d\n",
86 case WLAN_EID_VHT_CAPABILITY
:
87 sta_ptr
->is_11ac_enabled
= true;
88 vht_cap
= (void *)(ele_hdr
+ 2);
89 /* check VHT MAXMPDU capability */
90 switch (le32_to_cpu(vht_cap
->vht_cap_info
) & 0x3) {
91 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
:
93 MWIFIEX_TX_DATA_BUF_SIZE_12K
;
95 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
:
97 MWIFIEX_TX_DATA_BUF_SIZE_8K
;
99 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895
:
101 MWIFIEX_TX_DATA_BUF_SIZE_4K
;
106 mwifiex_dbg(priv
->adapter
, INFO
,
107 "11ac enabled!, max_amsdu : %d\n",
114 curr
+= (ele_len
+ sizeof(*ele_hdr
));
115 evt_len
-= (ele_len
+ sizeof(*ele_hdr
));
122 * This function resets the connection state.
124 * The function is invoked after receiving a disconnect event from firmware,
125 * and performs the following actions -
126 * - Set media status to disconnected
127 * - Clean up Tx and Rx packets
128 * - Resets SNR/NF/RSSI value in driver
129 * - Resets security configurations in driver
130 * - Enables auto data rate
131 * - Saves the previous SSID and BSSID so that they can
132 * be used for re-association, if required
133 * - Erases current SSID and BSSID information
134 * - Sends a disconnect event to upper layers/applications.
136 void mwifiex_reset_connect_state(struct mwifiex_private
*priv
, u16 reason_code
,
139 struct mwifiex_adapter
*adapter
= priv
->adapter
;
141 if (!priv
->media_connected
)
144 mwifiex_dbg(adapter
, INFO
,
145 "info: handles disconnect event\n");
147 priv
->media_connected
= false;
149 priv
->scan_block
= false;
150 priv
->port_open
= false;
152 if ((GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_STA
) &&
153 ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
)) {
154 mwifiex_disable_all_tdls_links(priv
);
156 if (priv
->adapter
->auto_tdls
)
157 mwifiex_clean_auto_tdls(priv
);
160 /* Free Tx and Rx packets, report disconnect to upper layer */
161 mwifiex_clean_txrx(priv
);
163 /* Reset SNR/NF/RSSI values */
164 priv
->data_rssi_last
= 0;
165 priv
->data_nf_last
= 0;
166 priv
->data_rssi_avg
= 0;
167 priv
->data_nf_avg
= 0;
168 priv
->bcn_rssi_last
= 0;
169 priv
->bcn_nf_last
= 0;
170 priv
->bcn_rssi_avg
= 0;
171 priv
->bcn_nf_avg
= 0;
173 priv
->rxpd_htinfo
= 0;
174 priv
->sec_info
.wpa_enabled
= false;
175 priv
->sec_info
.wpa2_enabled
= false;
176 priv
->wpa_ie_len
= 0;
178 priv
->sec_info
.wapi_enabled
= false;
179 priv
->wapi_ie_len
= 0;
180 priv
->sec_info
.wapi_key_on
= false;
182 priv
->sec_info
.encryption_mode
= 0;
184 /* Enable auto data rate */
185 priv
->is_data_rate_auto
= true;
188 priv
->assoc_resp_ht_param
= 0;
189 priv
->ht_param_present
= false;
191 if ((GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_STA
||
192 GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) && priv
->hist_data
)
193 mwifiex_hist_data_reset(priv
);
195 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
) {
196 priv
->adhoc_state
= ADHOC_IDLE
;
197 priv
->adhoc_is_link_sensed
= false;
201 * Memorize the previous SSID and BSSID so
202 * it could be used for re-assoc
205 mwifiex_dbg(adapter
, INFO
,
206 "info: previous SSID=%s, SSID len=%u\n",
207 priv
->prev_ssid
.ssid
, priv
->prev_ssid
.ssid_len
);
209 mwifiex_dbg(adapter
, INFO
,
210 "info: current SSID=%s, SSID len=%u\n",
211 priv
->curr_bss_params
.bss_descriptor
.ssid
.ssid
,
212 priv
->curr_bss_params
.bss_descriptor
.ssid
.ssid_len
);
214 memcpy(&priv
->prev_ssid
,
215 &priv
->curr_bss_params
.bss_descriptor
.ssid
,
216 sizeof(struct cfg80211_ssid
));
218 memcpy(priv
->prev_bssid
,
219 priv
->curr_bss_params
.bss_descriptor
.mac_address
, ETH_ALEN
);
221 /* Need to erase the current SSID and BSSID info */
222 memset(&priv
->curr_bss_params
, 0x00, sizeof(priv
->curr_bss_params
));
224 adapter
->tx_lock_flag
= false;
225 adapter
->pps_uapsd_mode
= false;
227 if (test_bit(MWIFIEX_IS_CMD_TIMEDOUT
, &adapter
->work_flags
) &&
230 priv
->media_connected
= false;
231 mwifiex_dbg(adapter
, MSG
,
232 "info: successfully disconnected from %pM: reason code %d\n",
233 priv
->cfg_bssid
, reason_code
);
234 if (priv
->bss_mode
== NL80211_IFTYPE_STATION
||
235 priv
->bss_mode
== NL80211_IFTYPE_P2P_CLIENT
) {
236 cfg80211_disconnected(priv
->netdev
, reason_code
, NULL
, 0,
237 !from_ap
, GFP_KERNEL
);
239 eth_zero_addr(priv
->cfg_bssid
);
241 mwifiex_stop_net_dev_queue(priv
->netdev
, adapter
);
242 if (netif_carrier_ok(priv
->netdev
))
243 netif_carrier_off(priv
->netdev
);
245 if (!ISSUPP_FIRMWARE_SUPPLICANT(priv
->adapter
->fw_cap_info
))
248 mwifiex_send_cmd(priv
, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG
,
249 HostCmd_ACT_GEN_REMOVE
, 0, NULL
, false);
252 static int mwifiex_parse_tdls_event(struct mwifiex_private
*priv
,
253 struct sk_buff
*event_skb
)
256 struct mwifiex_adapter
*adapter
= priv
->adapter
;
257 struct mwifiex_sta_node
*sta_ptr
;
258 struct mwifiex_tdls_generic_event
*tdls_evt
=
259 (void *)event_skb
->data
+ sizeof(adapter
->event_cause
);
260 u8
*mac
= tdls_evt
->peer_mac
;
262 /* reserved 2 bytes are not mandatory in tdls event */
263 if (event_skb
->len
< (sizeof(struct mwifiex_tdls_generic_event
) -
264 sizeof(u16
) - sizeof(adapter
->event_cause
))) {
265 mwifiex_dbg(adapter
, ERROR
, "Invalid event length!\n");
269 sta_ptr
= mwifiex_get_sta_entry(priv
, tdls_evt
->peer_mac
);
271 mwifiex_dbg(adapter
, ERROR
, "cannot get sta entry!\n");
275 switch (le16_to_cpu(tdls_evt
->type
)) {
276 case TDLS_EVENT_LINK_TEAR_DOWN
:
277 cfg80211_tdls_oper_request(priv
->netdev
,
279 NL80211_TDLS_TEARDOWN
,
280 le16_to_cpu(tdls_evt
->u
.reason_code
),
283 case TDLS_EVENT_CHAN_SWITCH_RESULT
:
284 mwifiex_dbg(adapter
, EVENT
, "tdls channel switch result :\n");
285 mwifiex_dbg(adapter
, EVENT
,
286 "status=0x%x, reason=0x%x cur_chan=%d\n",
287 tdls_evt
->u
.switch_result
.status
,
288 tdls_evt
->u
.switch_result
.reason
,
289 tdls_evt
->u
.switch_result
.cur_chan
);
291 /* tdls channel switch failed */
292 if (tdls_evt
->u
.switch_result
.status
!= 0) {
293 switch (tdls_evt
->u
.switch_result
.cur_chan
) {
294 case TDLS_BASE_CHANNEL
:
295 sta_ptr
->tdls_status
= TDLS_IN_BASE_CHAN
;
297 case TDLS_OFF_CHANNEL
:
298 sta_ptr
->tdls_status
= TDLS_IN_OFF_CHAN
;
306 /* tdls channel switch success */
307 switch (tdls_evt
->u
.switch_result
.cur_chan
) {
308 case TDLS_BASE_CHANNEL
:
309 if (sta_ptr
->tdls_status
== TDLS_IN_BASE_CHAN
)
311 mwifiex_update_ralist_tx_pause_in_tdls_cs(priv
, mac
,
313 sta_ptr
->tdls_status
= TDLS_IN_BASE_CHAN
;
315 case TDLS_OFF_CHANNEL
:
316 if (sta_ptr
->tdls_status
== TDLS_IN_OFF_CHAN
)
318 mwifiex_update_ralist_tx_pause_in_tdls_cs(priv
, mac
,
320 sta_ptr
->tdls_status
= TDLS_IN_OFF_CHAN
;
327 case TDLS_EVENT_START_CHAN_SWITCH
:
328 mwifiex_dbg(adapter
, EVENT
, "tdls start channel switch...\n");
329 sta_ptr
->tdls_status
= TDLS_CHAN_SWITCHING
;
331 case TDLS_EVENT_CHAN_SWITCH_STOPPED
:
332 mwifiex_dbg(adapter
, EVENT
,
333 "tdls chan switch stopped, reason=%d\n",
334 tdls_evt
->u
.cs_stop_reason
);
343 static void mwifiex_process_uap_tx_pause(struct mwifiex_private
*priv
,
344 struct mwifiex_ie_types_header
*tlv
)
346 struct mwifiex_tx_pause_tlv
*tp
;
347 struct mwifiex_sta_node
*sta_ptr
;
350 mwifiex_dbg(priv
->adapter
, EVENT
,
351 "uap tx_pause: %pM pause=%d, pkts=%d\n",
352 tp
->peermac
, tp
->tx_pause
,
355 if (ether_addr_equal(tp
->peermac
, priv
->netdev
->dev_addr
)) {
357 priv
->port_open
= false;
359 priv
->port_open
= true;
360 } else if (is_multicast_ether_addr(tp
->peermac
)) {
361 mwifiex_update_ralist_tx_pause(priv
, tp
->peermac
, tp
->tx_pause
);
363 spin_lock_bh(&priv
->sta_list_spinlock
);
364 sta_ptr
= mwifiex_get_sta_entry(priv
, tp
->peermac
);
365 if (sta_ptr
&& sta_ptr
->tx_pause
!= tp
->tx_pause
) {
366 sta_ptr
->tx_pause
= tp
->tx_pause
;
367 mwifiex_update_ralist_tx_pause(priv
, tp
->peermac
,
370 spin_unlock_bh(&priv
->sta_list_spinlock
);
374 static void mwifiex_process_sta_tx_pause(struct mwifiex_private
*priv
,
375 struct mwifiex_ie_types_header
*tlv
)
377 struct mwifiex_tx_pause_tlv
*tp
;
378 struct mwifiex_sta_node
*sta_ptr
;
382 mwifiex_dbg(priv
->adapter
, EVENT
,
383 "sta tx_pause: %pM pause=%d, pkts=%d\n",
384 tp
->peermac
, tp
->tx_pause
,
387 if (ether_addr_equal(tp
->peermac
, priv
->cfg_bssid
)) {
389 priv
->port_open
= false;
391 priv
->port_open
= true;
393 if (!ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
))
396 status
= mwifiex_get_tdls_link_status(priv
, tp
->peermac
);
397 if (mwifiex_is_tdls_link_setup(status
)) {
398 spin_lock_bh(&priv
->sta_list_spinlock
);
399 sta_ptr
= mwifiex_get_sta_entry(priv
, tp
->peermac
);
400 if (sta_ptr
&& sta_ptr
->tx_pause
!= tp
->tx_pause
) {
401 sta_ptr
->tx_pause
= tp
->tx_pause
;
402 mwifiex_update_ralist_tx_pause(priv
,
406 spin_unlock_bh(&priv
->sta_list_spinlock
);
411 void mwifiex_process_multi_chan_event(struct mwifiex_private
*priv
,
412 struct sk_buff
*event_skb
)
414 struct mwifiex_ie_types_multi_chan_info
*chan_info
;
415 struct mwifiex_ie_types_mc_group_info
*grp_info
;
416 struct mwifiex_adapter
*adapter
= priv
->adapter
;
417 struct mwifiex_ie_types_header
*tlv
;
418 u16 tlv_buf_left
, tlv_type
, tlv_len
;
419 int intf_num
, bss_type
, bss_num
, i
;
420 struct mwifiex_private
*intf_priv
;
422 tlv_buf_left
= event_skb
->len
- sizeof(u32
);
423 chan_info
= (void *)event_skb
->data
+ sizeof(u32
);
425 if (le16_to_cpu(chan_info
->header
.type
) != TLV_TYPE_MULTI_CHAN_INFO
||
426 tlv_buf_left
< sizeof(struct mwifiex_ie_types_multi_chan_info
)) {
427 mwifiex_dbg(adapter
, ERROR
,
428 "unknown TLV in chan_info event\n");
432 adapter
->usb_mc_status
= le16_to_cpu(chan_info
->status
);
433 mwifiex_dbg(adapter
, EVENT
, "multi chan operation %s\n",
434 adapter
->usb_mc_status
? "started" : "over");
436 tlv_buf_left
-= sizeof(struct mwifiex_ie_types_multi_chan_info
);
437 tlv
= (struct mwifiex_ie_types_header
*)chan_info
->tlv_buffer
;
439 while (tlv_buf_left
>= (int)sizeof(struct mwifiex_ie_types_header
)) {
440 tlv_type
= le16_to_cpu(tlv
->type
);
441 tlv_len
= le16_to_cpu(tlv
->len
);
442 if ((sizeof(struct mwifiex_ie_types_header
) + tlv_len
) >
444 mwifiex_dbg(adapter
, ERROR
, "wrong tlv: tlvLen=%d,\t"
445 "tlvBufLeft=%d\n", tlv_len
, tlv_buf_left
);
448 if (tlv_type
!= TLV_TYPE_MC_GROUP_INFO
) {
449 mwifiex_dbg(adapter
, ERROR
, "wrong tlv type: 0x%x\n",
454 grp_info
= (struct mwifiex_ie_types_mc_group_info
*)tlv
;
455 intf_num
= grp_info
->intf_num
;
456 for (i
= 0; i
< intf_num
; i
++) {
457 bss_type
= grp_info
->bss_type_numlist
[i
] >> 4;
458 bss_num
= grp_info
->bss_type_numlist
[i
] & BSS_NUM_MASK
;
459 intf_priv
= mwifiex_get_priv_by_id(adapter
, bss_num
,
462 mwifiex_dbg(adapter
, ERROR
,
463 "Invalid bss_type bss_num\t"
464 "in multi channel event\n");
467 if (adapter
->iface_type
== MWIFIEX_USB
) {
470 ep
= grp_info
->hid_num
.usb_ep_num
;
471 if (ep
== MWIFIEX_USB_EP_DATA
||
472 ep
== MWIFIEX_USB_EP_DATA_CH2
)
473 intf_priv
->usb_port
= ep
;
477 tlv_buf_left
-= sizeof(struct mwifiex_ie_types_header
) +
479 tlv
= (void *)((u8
*)tlv
+ tlv_len
+
480 sizeof(struct mwifiex_ie_types_header
));
483 if (adapter
->iface_type
== MWIFIEX_USB
) {
484 adapter
->tx_lock_flag
= true;
485 adapter
->usb_mc_setup
= true;
486 mwifiex_multi_chan_resync(adapter
);
490 void mwifiex_process_tx_pause_event(struct mwifiex_private
*priv
,
491 struct sk_buff
*event_skb
)
493 struct mwifiex_ie_types_header
*tlv
;
494 u16 tlv_type
, tlv_len
;
497 if (!priv
->media_connected
) {
498 mwifiex_dbg(priv
->adapter
, ERROR
,
499 "tx_pause event while disconnected; bss_role=%d\n",
504 tlv_buf_left
= event_skb
->len
- sizeof(u32
);
505 tlv
= (void *)event_skb
->data
+ sizeof(u32
);
507 while (tlv_buf_left
>= (int)sizeof(struct mwifiex_ie_types_header
)) {
508 tlv_type
= le16_to_cpu(tlv
->type
);
509 tlv_len
= le16_to_cpu(tlv
->len
);
510 if ((sizeof(struct mwifiex_ie_types_header
) + tlv_len
) >
512 mwifiex_dbg(priv
->adapter
, ERROR
,
513 "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
514 tlv_len
, tlv_buf_left
);
517 if (tlv_type
== TLV_TYPE_TX_PAUSE
) {
518 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_STA
)
519 mwifiex_process_sta_tx_pause(priv
, tlv
);
521 mwifiex_process_uap_tx_pause(priv
, tlv
);
524 tlv_buf_left
-= sizeof(struct mwifiex_ie_types_header
) +
526 tlv
= (void *)((u8
*)tlv
+ tlv_len
+
527 sizeof(struct mwifiex_ie_types_header
));
533 * This function handles coex events generated by firmware
535 void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private
*priv
,
536 struct sk_buff
*event_skb
)
538 struct mwifiex_adapter
*adapter
= priv
->adapter
;
539 struct mwifiex_ie_types_header
*tlv
;
540 struct mwifiex_ie_types_btcoex_aggr_win_size
*winsizetlv
;
541 struct mwifiex_ie_types_btcoex_scan_time
*scantlv
;
542 s32 len
= event_skb
->len
- sizeof(u32
);
543 u8
*cur_ptr
= event_skb
->data
+ sizeof(u32
);
544 u16 tlv_type
, tlv_len
;
546 while (len
>= sizeof(struct mwifiex_ie_types_header
)) {
547 tlv
= (struct mwifiex_ie_types_header
*)cur_ptr
;
548 tlv_len
= le16_to_cpu(tlv
->len
);
549 tlv_type
= le16_to_cpu(tlv
->type
);
551 if ((tlv_len
+ sizeof(struct mwifiex_ie_types_header
)) > len
)
554 case TLV_BTCOEX_WL_AGGR_WINSIZE
:
556 (struct mwifiex_ie_types_btcoex_aggr_win_size
*)tlv
;
557 adapter
->coex_win_size
= winsizetlv
->coex_win_size
;
558 adapter
->coex_tx_win_size
=
559 winsizetlv
->tx_win_size
;
560 adapter
->coex_rx_win_size
=
561 winsizetlv
->rx_win_size
;
562 mwifiex_coex_ampdu_rxwinsize(adapter
);
563 mwifiex_update_ampdu_txwinsize(adapter
);
566 case TLV_BTCOEX_WL_SCANTIME
:
568 (struct mwifiex_ie_types_btcoex_scan_time
*)tlv
;
569 adapter
->coex_scan
= scantlv
->coex_scan
;
570 adapter
->coex_min_scan_time
= le16_to_cpu(scantlv
->min_scan_time
);
571 adapter
->coex_max_scan_time
= le16_to_cpu(scantlv
->max_scan_time
);
578 len
-= tlv_len
+ sizeof(struct mwifiex_ie_types_header
);
580 sizeof(struct mwifiex_ie_types_header
);
583 dev_dbg(adapter
->dev
, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
584 adapter
->coex_scan
, adapter
->coex_min_scan_time
,
585 adapter
->coex_win_size
, adapter
->coex_tx_win_size
,
586 adapter
->coex_rx_win_size
);
590 mwifiex_fw_dump_info_event(struct mwifiex_private
*priv
,
591 struct sk_buff
*event_skb
)
593 struct mwifiex_adapter
*adapter
= priv
->adapter
;
594 struct mwifiex_fw_dump_header
*fw_dump_hdr
=
595 (void *)adapter
->event_body
;
597 if (adapter
->iface_type
!= MWIFIEX_USB
) {
598 mwifiex_dbg(adapter
, MSG
,
599 "event is not on usb interface, ignore it\n");
603 if (!adapter
->devdump_data
) {
604 /* When receive the first event, allocate device dump
605 * buffer, dump driver info.
607 adapter
->devdump_data
= vzalloc(MWIFIEX_FW_DUMP_SIZE
);
608 if (!adapter
->devdump_data
) {
609 mwifiex_dbg(adapter
, ERROR
,
610 "vzalloc devdump data failure!\n");
614 mwifiex_drv_info_dump(adapter
);
616 /* If no proceeded event arrive in 10s, upload device
617 * dump data, this will be useful if the end of
618 * transmission event get lost, in this cornel case,
619 * user would still get partial of the dump.
621 mod_timer(&adapter
->devdump_timer
,
622 jiffies
+ msecs_to_jiffies(MWIFIEX_TIMER_10S
));
626 if (adapter
->devdump_len
+ event_skb
->len
>= MWIFIEX_FW_DUMP_SIZE
)
629 memmove(adapter
->devdump_data
+ adapter
->devdump_len
,
630 adapter
->event_skb
->data
, event_skb
->len
);
631 adapter
->devdump_len
+= event_skb
->len
;
633 if (le16_to_cpu(fw_dump_hdr
->type
== FW_DUMP_INFO_ENDED
)) {
634 mwifiex_dbg(adapter
, MSG
,
635 "receive end of transmission flag event!\n");
641 del_timer_sync(&adapter
->devdump_timer
);
642 mwifiex_upload_device_dump(adapter
);
646 * This function handles events generated by firmware.
648 * This is a generic function and handles all events.
650 * Event specific routines are called by this function based
651 * upon the generated event cause.
653 * For the following events, the function just forwards them to upper
654 * layers, optionally recording the change -
655 * - EVENT_LINK_SENSED
656 * - EVENT_MIC_ERR_UNICAST
657 * - EVENT_MIC_ERR_MULTICAST
658 * - EVENT_PORT_RELEASE
664 * - EVENT_DATA_RSSI_LOW
665 * - EVENT_DATA_SNR_LOW
666 * - EVENT_DATA_RSSI_HIGH
667 * - EVENT_DATA_SNR_HIGH
668 * - EVENT_LINK_QUALITY
669 * - EVENT_PRE_BEACON_LOST
670 * - EVENT_IBSS_COALESCED
671 * - EVENT_IBSS_STA_CONNECT
672 * - EVENT_IBSS_STA_DISCONNECT
673 * - EVENT_WEP_ICV_ERR
675 * - EVENT_HOSTWAKE_STAIE
677 * For the following events, no action is taken -
678 * - EVENT_MIB_CHANGED
680 * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL
682 * Rest of the supported events requires driver handling -
683 * - EVENT_DEAUTHENTICATED
684 * - EVENT_DISASSOCIATED
688 * - EVENT_DEEP_SLEEP_AWAKE
690 * - EVENT_ADHOC_BCN_LOST
691 * - EVENT_BG_SCAN_REPORT
692 * - EVENT_WMM_STATUS_CHANGE
695 * - EVENT_BA_STREAM_TIEMOUT
696 * - EVENT_AMSDU_AGGR_CTRL
697 * - EVENT_FW_DUMP_INFO
699 int mwifiex_process_sta_event(struct mwifiex_private
*priv
)
701 struct mwifiex_adapter
*adapter
= priv
->adapter
;
703 u32 eventcause
= adapter
->event_cause
;
704 u16 ctrl
, reason_code
;
705 u8 ibss_sta_addr
[ETH_ALEN
];
706 struct mwifiex_sta_node
*sta_ptr
;
708 switch (eventcause
) {
709 case EVENT_DUMMY_HOST_WAKEUP_SIGNAL
:
710 mwifiex_dbg(adapter
, ERROR
,
711 "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
713 case EVENT_LINK_SENSED
:
714 mwifiex_dbg(adapter
, EVENT
, "event: LINK_SENSED\n");
715 if (!netif_carrier_ok(priv
->netdev
))
716 netif_carrier_on(priv
->netdev
);
717 mwifiex_wake_up_net_dev_queue(priv
->netdev
, adapter
);
720 case EVENT_DEAUTHENTICATED
:
721 mwifiex_dbg(adapter
, EVENT
, "event: Deauthenticated\n");
722 if (priv
->wps
.session_enable
) {
723 mwifiex_dbg(adapter
, INFO
,
724 "info: receive deauth event in wps session\n");
727 adapter
->dbg
.num_event_deauth
++;
728 if (priv
->media_connected
) {
730 get_unaligned_le16(adapter
->event_body
);
731 mwifiex_reset_connect_state(priv
, reason_code
, true);
735 case EVENT_DISASSOCIATED
:
736 mwifiex_dbg(adapter
, EVENT
, "event: Disassociated\n");
737 if (priv
->wps
.session_enable
) {
738 mwifiex_dbg(adapter
, INFO
,
739 "info: receive disassoc event in wps session\n");
742 adapter
->dbg
.num_event_disassoc
++;
743 if (priv
->media_connected
) {
745 get_unaligned_le16(adapter
->event_body
);
746 mwifiex_reset_connect_state(priv
, reason_code
, true);
750 case EVENT_LINK_LOST
:
751 mwifiex_dbg(adapter
, EVENT
, "event: Link lost\n");
752 adapter
->dbg
.num_event_link_lost
++;
753 if (priv
->media_connected
) {
755 get_unaligned_le16(adapter
->event_body
);
756 mwifiex_reset_connect_state(priv
, reason_code
, true);
761 mwifiex_dbg(adapter
, EVENT
, "info: EVENT: SLEEP\n");
763 adapter
->ps_state
= PS_STATE_PRE_SLEEP
;
765 mwifiex_check_ps_cond(adapter
);
769 mwifiex_dbg(adapter
, EVENT
, "info: EVENT: AWAKE\n");
770 if (!adapter
->pps_uapsd_mode
&&
772 (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
)) &&
773 priv
->media_connected
&& adapter
->sleep_period
.period
) {
774 adapter
->pps_uapsd_mode
= true;
775 mwifiex_dbg(adapter
, EVENT
,
776 "event: PPS/UAPSD mode activated\n");
778 adapter
->tx_lock_flag
= false;
779 if (adapter
->pps_uapsd_mode
&& adapter
->gen_null_pkt
) {
780 if (mwifiex_check_last_packet_indication(priv
)) {
781 if (adapter
->data_sent
||
782 (adapter
->if_ops
.is_port_ready
&&
783 !adapter
->if_ops
.is_port_ready(priv
))) {
784 adapter
->ps_state
= PS_STATE_AWAKE
;
785 adapter
->pm_wakeup_card_req
= false;
786 adapter
->pm_wakeup_fw_try
= false;
787 del_timer(&adapter
->wakeup_timer
);
790 if (!mwifiex_send_null_packet
792 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET
|
793 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET
))
799 adapter
->ps_state
= PS_STATE_AWAKE
;
800 adapter
->pm_wakeup_card_req
= false;
801 adapter
->pm_wakeup_fw_try
= false;
802 del_timer(&adapter
->wakeup_timer
);
806 case EVENT_DEEP_SLEEP_AWAKE
:
807 adapter
->if_ops
.wakeup_complete(adapter
);
808 mwifiex_dbg(adapter
, EVENT
, "event: DS_AWAKE\n");
809 if (adapter
->is_deep_sleep
)
810 adapter
->is_deep_sleep
= false;
813 case EVENT_HS_ACT_REQ
:
814 mwifiex_dbg(adapter
, EVENT
, "event: HS_ACT_REQ\n");
815 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_HS_CFG_ENH
,
819 case EVENT_MIC_ERR_UNICAST
:
820 mwifiex_dbg(adapter
, EVENT
, "event: UNICAST MIC ERROR\n");
821 cfg80211_michael_mic_failure(priv
->netdev
, priv
->cfg_bssid
,
822 NL80211_KEYTYPE_PAIRWISE
,
823 -1, NULL
, GFP_KERNEL
);
826 case EVENT_MIC_ERR_MULTICAST
:
827 mwifiex_dbg(adapter
, EVENT
, "event: MULTICAST MIC ERROR\n");
828 cfg80211_michael_mic_failure(priv
->netdev
, priv
->cfg_bssid
,
829 NL80211_KEYTYPE_GROUP
,
830 -1, NULL
, GFP_KERNEL
);
832 case EVENT_MIB_CHANGED
:
833 case EVENT_INIT_DONE
:
836 case EVENT_ADHOC_BCN_LOST
:
837 mwifiex_dbg(adapter
, EVENT
, "event: ADHOC_BCN_LOST\n");
838 priv
->adhoc_is_link_sensed
= false;
839 mwifiex_clean_txrx(priv
);
840 mwifiex_stop_net_dev_queue(priv
->netdev
, adapter
);
841 if (netif_carrier_ok(priv
->netdev
))
842 netif_carrier_off(priv
->netdev
);
845 case EVENT_BG_SCAN_REPORT
:
846 mwifiex_dbg(adapter
, EVENT
, "event: BGS_REPORT\n");
847 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_BG_SCAN_QUERY
,
848 HostCmd_ACT_GEN_GET
, 0, NULL
, false);
851 case EVENT_BG_SCAN_STOPPED
:
852 dev_dbg(adapter
->dev
, "event: BGS_STOPPED\n");
853 cfg80211_sched_scan_stopped(priv
->wdev
.wiphy
, 0);
854 if (priv
->sched_scanning
)
855 priv
->sched_scanning
= false;
858 case EVENT_PORT_RELEASE
:
859 mwifiex_dbg(adapter
, EVENT
, "event: PORT RELEASE\n");
860 priv
->port_open
= true;
863 case EVENT_EXT_SCAN_REPORT
:
864 mwifiex_dbg(adapter
, EVENT
, "event: EXT_SCAN Report\n");
865 /* We intend to skip this event during suspend, but handle
866 * it in interface disabled case
868 if (adapter
->ext_scan
&& (!priv
->scan_aborting
||
869 !netif_running(priv
->netdev
)))
870 ret
= mwifiex_handle_event_ext_scan_report(priv
,
871 adapter
->event_skb
->data
);
875 case EVENT_WMM_STATUS_CHANGE
:
876 mwifiex_dbg(adapter
, EVENT
, "event: WMM status changed\n");
877 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_WMM_GET_STATUS
,
882 cfg80211_cqm_rssi_notify(priv
->netdev
,
883 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW
,
885 mwifiex_send_cmd(priv
, HostCmd_CMD_RSSI_INFO
,
886 HostCmd_ACT_GEN_GET
, 0, NULL
, false);
887 priv
->subsc_evt_rssi_state
= RSSI_LOW_RECVD
;
888 mwifiex_dbg(adapter
, EVENT
, "event: Beacon RSSI_LOW\n");
891 mwifiex_dbg(adapter
, EVENT
, "event: Beacon SNR_LOW\n");
894 mwifiex_dbg(adapter
, EVENT
, "event: MAX_FAIL\n");
896 case EVENT_RSSI_HIGH
:
897 cfg80211_cqm_rssi_notify(priv
->netdev
,
898 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH
,
900 mwifiex_send_cmd(priv
, HostCmd_CMD_RSSI_INFO
,
901 HostCmd_ACT_GEN_GET
, 0, NULL
, false);
902 priv
->subsc_evt_rssi_state
= RSSI_HIGH_RECVD
;
903 mwifiex_dbg(adapter
, EVENT
, "event: Beacon RSSI_HIGH\n");
906 mwifiex_dbg(adapter
, EVENT
, "event: Beacon SNR_HIGH\n");
908 case EVENT_DATA_RSSI_LOW
:
909 mwifiex_dbg(adapter
, EVENT
, "event: Data RSSI_LOW\n");
911 case EVENT_DATA_SNR_LOW
:
912 mwifiex_dbg(adapter
, EVENT
, "event: Data SNR_LOW\n");
914 case EVENT_DATA_RSSI_HIGH
:
915 mwifiex_dbg(adapter
, EVENT
, "event: Data RSSI_HIGH\n");
917 case EVENT_DATA_SNR_HIGH
:
918 mwifiex_dbg(adapter
, EVENT
, "event: Data SNR_HIGH\n");
920 case EVENT_LINK_QUALITY
:
921 mwifiex_dbg(adapter
, EVENT
, "event: Link Quality\n");
923 case EVENT_PRE_BEACON_LOST
:
924 mwifiex_dbg(adapter
, EVENT
, "event: Pre-Beacon Lost\n");
926 case EVENT_IBSS_COALESCED
:
927 mwifiex_dbg(adapter
, EVENT
, "event: IBSS_COALESCED\n");
928 ret
= mwifiex_send_cmd(priv
,
929 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
,
930 HostCmd_ACT_GEN_GET
, 0, NULL
, false);
932 case EVENT_IBSS_STA_CONNECT
:
933 ether_addr_copy(ibss_sta_addr
, adapter
->event_body
+ 2);
934 mwifiex_dbg(adapter
, EVENT
, "event: IBSS_STA_CONNECT %pM\n",
936 sta_ptr
= mwifiex_add_sta_entry(priv
, ibss_sta_addr
);
937 if (sta_ptr
&& adapter
->adhoc_11n_enabled
) {
938 mwifiex_check_ibss_peer_capabilities(priv
, sta_ptr
,
940 if (sta_ptr
->is_11n_enabled
)
941 for (i
= 0; i
< MAX_NUM_TID
; i
++)
942 sta_ptr
->ampdu_sta
[i
] =
943 priv
->aggr_prio_tbl
[i
].ampdu_user
;
945 for (i
= 0; i
< MAX_NUM_TID
; i
++)
946 sta_ptr
->ampdu_sta
[i
] =
947 BA_STREAM_NOT_ALLOWED
;
948 memset(sta_ptr
->rx_seq
, 0xff, sizeof(sta_ptr
->rx_seq
));
952 case EVENT_IBSS_STA_DISCONNECT
:
953 ether_addr_copy(ibss_sta_addr
, adapter
->event_body
+ 2);
954 mwifiex_dbg(adapter
, EVENT
, "event: IBSS_STA_DISCONNECT %pM\n",
956 sta_ptr
= mwifiex_get_sta_entry(priv
, ibss_sta_addr
);
957 if (sta_ptr
&& sta_ptr
->is_11n_enabled
) {
958 mwifiex_11n_del_rx_reorder_tbl_by_ta(priv
,
960 mwifiex_del_tx_ba_stream_tbl_by_ra(priv
, ibss_sta_addr
);
962 mwifiex_wmm_del_peer_ra_list(priv
, ibss_sta_addr
);
963 mwifiex_del_sta_entry(priv
, ibss_sta_addr
);
966 mwifiex_dbg(adapter
, EVENT
, "event: ADDBA Request\n");
967 mwifiex_send_cmd(priv
, HostCmd_CMD_11N_ADDBA_RSP
,
968 HostCmd_ACT_GEN_SET
, 0,
969 adapter
->event_body
, false);
972 mwifiex_dbg(adapter
, EVENT
, "event: DELBA Request\n");
973 mwifiex_11n_delete_ba_stream(priv
, adapter
->event_body
);
975 case EVENT_BA_STREAM_TIEMOUT
:
976 mwifiex_dbg(adapter
, EVENT
, "event: BA Stream timeout\n");
977 mwifiex_11n_ba_stream_timeout(priv
,
978 (struct host_cmd_ds_11n_batimeout
980 adapter
->event_body
);
982 case EVENT_AMSDU_AGGR_CTRL
:
983 ctrl
= get_unaligned_le16(adapter
->event_body
);
984 mwifiex_dbg(adapter
, EVENT
,
985 "event: AMSDU_AGGR_CTRL %d\n", ctrl
);
987 adapter
->tx_buf_size
=
988 min_t(u16
, adapter
->curr_tx_buf_size
, ctrl
);
989 mwifiex_dbg(adapter
, EVENT
, "event: tx_buf_size %d\n",
990 adapter
->tx_buf_size
);
993 case EVENT_WEP_ICV_ERR
:
994 mwifiex_dbg(adapter
, EVENT
, "event: WEP ICV error\n");
997 case EVENT_BW_CHANGE
:
998 mwifiex_dbg(adapter
, EVENT
, "event: BW Change\n");
1001 case EVENT_HOSTWAKE_STAIE
:
1002 mwifiex_dbg(adapter
, EVENT
,
1003 "event: HOSTWAKE_STAIE %d\n", eventcause
);
1006 case EVENT_REMAIN_ON_CHAN_EXPIRED
:
1007 mwifiex_dbg(adapter
, EVENT
,
1008 "event: Remain on channel expired\n");
1009 cfg80211_remain_on_channel_expired(&priv
->wdev
,
1010 priv
->roc_cfg
.cookie
,
1011 &priv
->roc_cfg
.chan
,
1014 memset(&priv
->roc_cfg
, 0x00, sizeof(struct mwifiex_roc_cfg
));
1018 case EVENT_CHANNEL_SWITCH_ANN
:
1019 mwifiex_dbg(adapter
, EVENT
, "event: Channel Switch Announcement\n");
1020 priv
->csa_expire_time
=
1021 jiffies
+ msecs_to_jiffies(DFS_CHAN_MOVE_TIME
);
1022 priv
->csa_chan
= priv
->curr_bss_params
.bss_descriptor
.channel
;
1023 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_DEAUTHENTICATE
,
1024 HostCmd_ACT_GEN_SET
, 0,
1025 priv
->curr_bss_params
.bss_descriptor
.mac_address
,
1029 case EVENT_TDLS_GENERIC_EVENT
:
1030 ret
= mwifiex_parse_tdls_event(priv
, adapter
->event_skb
);
1033 case EVENT_TX_DATA_PAUSE
:
1034 mwifiex_dbg(adapter
, EVENT
, "event: TX DATA PAUSE\n");
1035 mwifiex_process_tx_pause_event(priv
, adapter
->event_skb
);
1038 case EVENT_MULTI_CHAN_INFO
:
1039 mwifiex_dbg(adapter
, EVENT
, "event: multi-chan info\n");
1040 mwifiex_process_multi_chan_event(priv
, adapter
->event_skb
);
1043 case EVENT_TX_STATUS_REPORT
:
1044 mwifiex_dbg(adapter
, EVENT
, "event: TX_STATUS Report\n");
1045 mwifiex_parse_tx_status_event(priv
, adapter
->event_body
);
1048 case EVENT_CHANNEL_REPORT_RDY
:
1049 mwifiex_dbg(adapter
, EVENT
, "event: Channel Report\n");
1050 ret
= mwifiex_11h_handle_chanrpt_ready(priv
,
1051 adapter
->event_skb
);
1053 case EVENT_RADAR_DETECTED
:
1054 mwifiex_dbg(adapter
, EVENT
, "event: Radar detected\n");
1055 ret
= mwifiex_11h_handle_radar_detected(priv
,
1056 adapter
->event_skb
);
1058 case EVENT_BT_COEX_WLAN_PARA_CHANGE
:
1059 dev_dbg(adapter
->dev
, "EVENT: BT coex wlan param update\n");
1060 mwifiex_bt_coex_wlan_param_update_event(priv
,
1061 adapter
->event_skb
);
1063 case EVENT_RXBA_SYNC
:
1064 dev_dbg(adapter
->dev
, "EVENT: RXBA_SYNC\n");
1065 mwifiex_11n_rxba_sync_event(priv
, adapter
->event_body
,
1066 adapter
->event_skb
->len
-
1067 sizeof(eventcause
));
1069 case EVENT_FW_DUMP_INFO
:
1070 mwifiex_dbg(adapter
, EVENT
, "event: firmware debug info\n");
1071 mwifiex_fw_dump_info_event(priv
, adapter
->event_skb
);
1073 /* Debugging event; not used, but let's not print an ERROR for it. */
1074 case EVENT_UNKNOWN_DEBUG
:
1075 mwifiex_dbg(adapter
, EVENT
, "event: debug\n");
1078 mwifiex_dbg(adapter
, ERROR
, "event: unknown event id: %#x\n",