162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * NXP Wireless LAN device driver: station event handling 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011-2020 NXP 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "decl.h" 962306a36Sopenharmony_ci#include "ioctl.h" 1062306a36Sopenharmony_ci#include "util.h" 1162306a36Sopenharmony_ci#include "fw.h" 1262306a36Sopenharmony_ci#include "main.h" 1362306a36Sopenharmony_ci#include "wmm.h" 1462306a36Sopenharmony_ci#include "11n.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE 12 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic int mwifiex_check_ibss_peer_capabilities(struct mwifiex_private *priv, 1962306a36Sopenharmony_ci struct mwifiex_sta_node *sta_ptr, 2062306a36Sopenharmony_ci struct sk_buff *event) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci int evt_len, ele_len; 2362306a36Sopenharmony_ci u8 *curr; 2462306a36Sopenharmony_ci struct ieee_types_header *ele_hdr; 2562306a36Sopenharmony_ci struct mwifiex_ie_types_mgmt_frame *tlv_mgmt_frame; 2662306a36Sopenharmony_ci const struct ieee80211_ht_cap *ht_cap; 2762306a36Sopenharmony_ci const struct ieee80211_vht_cap *vht_cap; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci skb_pull(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE); 3062306a36Sopenharmony_ci evt_len = event->len; 3162306a36Sopenharmony_ci curr = event->data; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci mwifiex_dbg_dump(priv->adapter, EVT_D, "ibss peer capabilities:", 3462306a36Sopenharmony_ci event->data, event->len); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci skb_push(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci tlv_mgmt_frame = (void *)curr; 3962306a36Sopenharmony_ci if (evt_len >= sizeof(*tlv_mgmt_frame) && 4062306a36Sopenharmony_ci le16_to_cpu(tlv_mgmt_frame->header.type) == 4162306a36Sopenharmony_ci TLV_TYPE_UAP_MGMT_FRAME) { 4262306a36Sopenharmony_ci /* Locate curr pointer to the start of beacon tlv, 4362306a36Sopenharmony_ci * timestamp 8 bytes, beacon intervel 2 bytes, 4462306a36Sopenharmony_ci * capability info 2 bytes, totally 12 byte beacon header 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci evt_len = le16_to_cpu(tlv_mgmt_frame->header.len); 4762306a36Sopenharmony_ci curr += (sizeof(*tlv_mgmt_frame) + 12); 4862306a36Sopenharmony_ci } else { 4962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 5062306a36Sopenharmony_ci "management frame tlv not found!\n"); 5162306a36Sopenharmony_ci return 0; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci while (evt_len >= sizeof(*ele_hdr)) { 5562306a36Sopenharmony_ci ele_hdr = (struct ieee_types_header *)curr; 5662306a36Sopenharmony_ci ele_len = ele_hdr->len; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (evt_len < ele_len + sizeof(*ele_hdr)) 5962306a36Sopenharmony_ci break; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci switch (ele_hdr->element_id) { 6262306a36Sopenharmony_ci case WLAN_EID_HT_CAPABILITY: 6362306a36Sopenharmony_ci sta_ptr->is_11n_enabled = true; 6462306a36Sopenharmony_ci ht_cap = (void *)(ele_hdr + 2); 6562306a36Sopenharmony_ci sta_ptr->max_amsdu = le16_to_cpu(ht_cap->cap_info) & 6662306a36Sopenharmony_ci IEEE80211_HT_CAP_MAX_AMSDU ? 6762306a36Sopenharmony_ci MWIFIEX_TX_DATA_BUF_SIZE_8K : 6862306a36Sopenharmony_ci MWIFIEX_TX_DATA_BUF_SIZE_4K; 6962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 7062306a36Sopenharmony_ci "11n enabled!, max_amsdu : %d\n", 7162306a36Sopenharmony_ci sta_ptr->max_amsdu); 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci case WLAN_EID_VHT_CAPABILITY: 7562306a36Sopenharmony_ci sta_ptr->is_11ac_enabled = true; 7662306a36Sopenharmony_ci vht_cap = (void *)(ele_hdr + 2); 7762306a36Sopenharmony_ci /* check VHT MAXMPDU capability */ 7862306a36Sopenharmony_ci switch (le32_to_cpu(vht_cap->vht_cap_info) & 0x3) { 7962306a36Sopenharmony_ci case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: 8062306a36Sopenharmony_ci sta_ptr->max_amsdu = 8162306a36Sopenharmony_ci MWIFIEX_TX_DATA_BUF_SIZE_12K; 8262306a36Sopenharmony_ci break; 8362306a36Sopenharmony_ci case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: 8462306a36Sopenharmony_ci sta_ptr->max_amsdu = 8562306a36Sopenharmony_ci MWIFIEX_TX_DATA_BUF_SIZE_8K; 8662306a36Sopenharmony_ci break; 8762306a36Sopenharmony_ci case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895: 8862306a36Sopenharmony_ci sta_ptr->max_amsdu = 8962306a36Sopenharmony_ci MWIFIEX_TX_DATA_BUF_SIZE_4K; 9062306a36Sopenharmony_ci break; 9162306a36Sopenharmony_ci default: 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 9662306a36Sopenharmony_ci "11ac enabled!, max_amsdu : %d\n", 9762306a36Sopenharmony_ci sta_ptr->max_amsdu); 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci default: 10062306a36Sopenharmony_ci break; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci curr += (ele_len + sizeof(*ele_hdr)); 10462306a36Sopenharmony_ci evt_len -= (ele_len + sizeof(*ele_hdr)); 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* 11162306a36Sopenharmony_ci * This function resets the connection state. 11262306a36Sopenharmony_ci * 11362306a36Sopenharmony_ci * The function is invoked after receiving a disconnect event from firmware, 11462306a36Sopenharmony_ci * and performs the following actions - 11562306a36Sopenharmony_ci * - Set media status to disconnected 11662306a36Sopenharmony_ci * - Clean up Tx and Rx packets 11762306a36Sopenharmony_ci * - Resets SNR/NF/RSSI value in driver 11862306a36Sopenharmony_ci * - Resets security configurations in driver 11962306a36Sopenharmony_ci * - Enables auto data rate 12062306a36Sopenharmony_ci * - Saves the previous SSID and BSSID so that they can 12162306a36Sopenharmony_ci * be used for re-association, if required 12262306a36Sopenharmony_ci * - Erases current SSID and BSSID information 12362306a36Sopenharmony_ci * - Sends a disconnect event to upper layers/applications. 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_civoid mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code, 12662306a36Sopenharmony_ci bool from_ap) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (!priv->media_connected) 13162306a36Sopenharmony_ci return; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 13462306a36Sopenharmony_ci "info: handles disconnect event\n"); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci priv->media_connected = false; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci priv->scan_block = false; 13962306a36Sopenharmony_ci priv->port_open = false; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && 14262306a36Sopenharmony_ci ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) { 14362306a36Sopenharmony_ci mwifiex_disable_all_tdls_links(priv); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (priv->adapter->auto_tdls) 14662306a36Sopenharmony_ci mwifiex_clean_auto_tdls(priv); 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* Free Tx and Rx packets, report disconnect to upper layer */ 15062306a36Sopenharmony_ci mwifiex_clean_txrx(priv); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci /* Reset SNR/NF/RSSI values */ 15362306a36Sopenharmony_ci priv->data_rssi_last = 0; 15462306a36Sopenharmony_ci priv->data_nf_last = 0; 15562306a36Sopenharmony_ci priv->data_rssi_avg = 0; 15662306a36Sopenharmony_ci priv->data_nf_avg = 0; 15762306a36Sopenharmony_ci priv->bcn_rssi_last = 0; 15862306a36Sopenharmony_ci priv->bcn_nf_last = 0; 15962306a36Sopenharmony_ci priv->bcn_rssi_avg = 0; 16062306a36Sopenharmony_ci priv->bcn_nf_avg = 0; 16162306a36Sopenharmony_ci priv->rxpd_rate = 0; 16262306a36Sopenharmony_ci priv->rxpd_htinfo = 0; 16362306a36Sopenharmony_ci priv->sec_info.wpa_enabled = false; 16462306a36Sopenharmony_ci priv->sec_info.wpa2_enabled = false; 16562306a36Sopenharmony_ci priv->wpa_ie_len = 0; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci priv->sec_info.wapi_enabled = false; 16862306a36Sopenharmony_ci priv->wapi_ie_len = 0; 16962306a36Sopenharmony_ci priv->sec_info.wapi_key_on = false; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci priv->sec_info.encryption_mode = 0; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* Enable auto data rate */ 17462306a36Sopenharmony_ci priv->is_data_rate_auto = true; 17562306a36Sopenharmony_ci priv->data_rate = 0; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci priv->assoc_resp_ht_param = 0; 17862306a36Sopenharmony_ci priv->ht_param_present = false; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || 18162306a36Sopenharmony_ci GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data) 18262306a36Sopenharmony_ci mwifiex_hist_data_reset(priv); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { 18562306a36Sopenharmony_ci priv->adhoc_state = ADHOC_IDLE; 18662306a36Sopenharmony_ci priv->adhoc_is_link_sensed = false; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* 19062306a36Sopenharmony_ci * Memorize the previous SSID and BSSID so 19162306a36Sopenharmony_ci * it could be used for re-assoc 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 19562306a36Sopenharmony_ci "info: previous SSID=%s, SSID len=%u\n", 19662306a36Sopenharmony_ci priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 19962306a36Sopenharmony_ci "info: current SSID=%s, SSID len=%u\n", 20062306a36Sopenharmony_ci priv->curr_bss_params.bss_descriptor.ssid.ssid, 20162306a36Sopenharmony_ci priv->curr_bss_params.bss_descriptor.ssid.ssid_len); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci memcpy(&priv->prev_ssid, 20462306a36Sopenharmony_ci &priv->curr_bss_params.bss_descriptor.ssid, 20562306a36Sopenharmony_ci sizeof(struct cfg80211_ssid)); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci memcpy(priv->prev_bssid, 20862306a36Sopenharmony_ci priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* Need to erase the current SSID and BSSID info */ 21162306a36Sopenharmony_ci memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci adapter->tx_lock_flag = false; 21462306a36Sopenharmony_ci adapter->pps_uapsd_mode = false; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags) && 21762306a36Sopenharmony_ci adapter->curr_cmd) 21862306a36Sopenharmony_ci return; 21962306a36Sopenharmony_ci priv->media_connected = false; 22062306a36Sopenharmony_ci mwifiex_dbg(adapter, MSG, 22162306a36Sopenharmony_ci "info: successfully disconnected from %pM: reason code %d\n", 22262306a36Sopenharmony_ci priv->cfg_bssid, reason_code); 22362306a36Sopenharmony_ci if (priv->bss_mode == NL80211_IFTYPE_STATION || 22462306a36Sopenharmony_ci priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { 22562306a36Sopenharmony_ci cfg80211_disconnected(priv->netdev, reason_code, NULL, 0, 22662306a36Sopenharmony_ci !from_ap, GFP_KERNEL); 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci eth_zero_addr(priv->cfg_bssid); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci mwifiex_stop_net_dev_queue(priv->netdev, adapter); 23162306a36Sopenharmony_ci if (netif_carrier_ok(priv->netdev)) 23262306a36Sopenharmony_ci netif_carrier_off(priv->netdev); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info)) 23562306a36Sopenharmony_ci return; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG, 23862306a36Sopenharmony_ci HostCmd_ACT_GEN_REMOVE, 0, NULL, false); 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic int mwifiex_parse_tdls_event(struct mwifiex_private *priv, 24262306a36Sopenharmony_ci struct sk_buff *event_skb) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci int ret = 0; 24562306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 24662306a36Sopenharmony_ci struct mwifiex_sta_node *sta_ptr; 24762306a36Sopenharmony_ci struct mwifiex_tdls_generic_event *tdls_evt = 24862306a36Sopenharmony_ci (void *)event_skb->data + sizeof(adapter->event_cause); 24962306a36Sopenharmony_ci u8 *mac = tdls_evt->peer_mac; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* reserved 2 bytes are not mandatory in tdls event */ 25262306a36Sopenharmony_ci if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) - 25362306a36Sopenharmony_ci sizeof(u16) - sizeof(adapter->event_cause))) { 25462306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, "Invalid event length!\n"); 25562306a36Sopenharmony_ci return -1; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac); 25962306a36Sopenharmony_ci if (!sta_ptr) { 26062306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, "cannot get sta entry!\n"); 26162306a36Sopenharmony_ci return -1; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci switch (le16_to_cpu(tdls_evt->type)) { 26562306a36Sopenharmony_ci case TDLS_EVENT_LINK_TEAR_DOWN: 26662306a36Sopenharmony_ci cfg80211_tdls_oper_request(priv->netdev, 26762306a36Sopenharmony_ci tdls_evt->peer_mac, 26862306a36Sopenharmony_ci NL80211_TDLS_TEARDOWN, 26962306a36Sopenharmony_ci le16_to_cpu(tdls_evt->u.reason_code), 27062306a36Sopenharmony_ci GFP_KERNEL); 27162306a36Sopenharmony_ci break; 27262306a36Sopenharmony_ci case TDLS_EVENT_CHAN_SWITCH_RESULT: 27362306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "tdls channel switch result :\n"); 27462306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, 27562306a36Sopenharmony_ci "status=0x%x, reason=0x%x cur_chan=%d\n", 27662306a36Sopenharmony_ci tdls_evt->u.switch_result.status, 27762306a36Sopenharmony_ci tdls_evt->u.switch_result.reason, 27862306a36Sopenharmony_ci tdls_evt->u.switch_result.cur_chan); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* tdls channel switch failed */ 28162306a36Sopenharmony_ci if (tdls_evt->u.switch_result.status != 0) { 28262306a36Sopenharmony_ci switch (tdls_evt->u.switch_result.cur_chan) { 28362306a36Sopenharmony_ci case TDLS_BASE_CHANNEL: 28462306a36Sopenharmony_ci sta_ptr->tdls_status = TDLS_IN_BASE_CHAN; 28562306a36Sopenharmony_ci break; 28662306a36Sopenharmony_ci case TDLS_OFF_CHANNEL: 28762306a36Sopenharmony_ci sta_ptr->tdls_status = TDLS_IN_OFF_CHAN; 28862306a36Sopenharmony_ci break; 28962306a36Sopenharmony_ci default: 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci return ret; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* tdls channel switch success */ 29662306a36Sopenharmony_ci switch (tdls_evt->u.switch_result.cur_chan) { 29762306a36Sopenharmony_ci case TDLS_BASE_CHANNEL: 29862306a36Sopenharmony_ci if (sta_ptr->tdls_status == TDLS_IN_BASE_CHAN) 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac, 30162306a36Sopenharmony_ci false); 30262306a36Sopenharmony_ci sta_ptr->tdls_status = TDLS_IN_BASE_CHAN; 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci case TDLS_OFF_CHANNEL: 30562306a36Sopenharmony_ci if (sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac, 30862306a36Sopenharmony_ci true); 30962306a36Sopenharmony_ci sta_ptr->tdls_status = TDLS_IN_OFF_CHAN; 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci default: 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci break; 31662306a36Sopenharmony_ci case TDLS_EVENT_START_CHAN_SWITCH: 31762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "tdls start channel switch...\n"); 31862306a36Sopenharmony_ci sta_ptr->tdls_status = TDLS_CHAN_SWITCHING; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci case TDLS_EVENT_CHAN_SWITCH_STOPPED: 32162306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, 32262306a36Sopenharmony_ci "tdls chan switch stopped, reason=%d\n", 32362306a36Sopenharmony_ci tdls_evt->u.cs_stop_reason); 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci default: 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci return ret; 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv, 33362306a36Sopenharmony_ci struct mwifiex_ie_types_header *tlv) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct mwifiex_tx_pause_tlv *tp; 33662306a36Sopenharmony_ci struct mwifiex_sta_node *sta_ptr; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci tp = (void *)tlv; 33962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, EVENT, 34062306a36Sopenharmony_ci "uap tx_pause: %pM pause=%d, pkts=%d\n", 34162306a36Sopenharmony_ci tp->peermac, tp->tx_pause, 34262306a36Sopenharmony_ci tp->pkt_cnt); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) { 34562306a36Sopenharmony_ci if (tp->tx_pause) 34662306a36Sopenharmony_ci priv->port_open = false; 34762306a36Sopenharmony_ci else 34862306a36Sopenharmony_ci priv->port_open = true; 34962306a36Sopenharmony_ci } else if (is_multicast_ether_addr(tp->peermac)) { 35062306a36Sopenharmony_ci mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause); 35162306a36Sopenharmony_ci } else { 35262306a36Sopenharmony_ci spin_lock_bh(&priv->sta_list_spinlock); 35362306a36Sopenharmony_ci sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac); 35462306a36Sopenharmony_ci if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) { 35562306a36Sopenharmony_ci sta_ptr->tx_pause = tp->tx_pause; 35662306a36Sopenharmony_ci spin_unlock_bh(&priv->sta_list_spinlock); 35762306a36Sopenharmony_ci mwifiex_update_ralist_tx_pause(priv, tp->peermac, 35862306a36Sopenharmony_ci tp->tx_pause); 35962306a36Sopenharmony_ci } else { 36062306a36Sopenharmony_ci spin_unlock_bh(&priv->sta_list_spinlock); 36162306a36Sopenharmony_ci } 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv, 36662306a36Sopenharmony_ci struct mwifiex_ie_types_header *tlv) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci struct mwifiex_tx_pause_tlv *tp; 36962306a36Sopenharmony_ci struct mwifiex_sta_node *sta_ptr; 37062306a36Sopenharmony_ci int status; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci tp = (void *)tlv; 37362306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, EVENT, 37462306a36Sopenharmony_ci "sta tx_pause: %pM pause=%d, pkts=%d\n", 37562306a36Sopenharmony_ci tp->peermac, tp->tx_pause, 37662306a36Sopenharmony_ci tp->pkt_cnt); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) { 37962306a36Sopenharmony_ci if (tp->tx_pause) 38062306a36Sopenharmony_ci priv->port_open = false; 38162306a36Sopenharmony_ci else 38262306a36Sopenharmony_ci priv->port_open = true; 38362306a36Sopenharmony_ci } else { 38462306a36Sopenharmony_ci if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) 38562306a36Sopenharmony_ci return; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci status = mwifiex_get_tdls_link_status(priv, tp->peermac); 38862306a36Sopenharmony_ci if (mwifiex_is_tdls_link_setup(status)) { 38962306a36Sopenharmony_ci spin_lock_bh(&priv->sta_list_spinlock); 39062306a36Sopenharmony_ci sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac); 39162306a36Sopenharmony_ci if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) { 39262306a36Sopenharmony_ci sta_ptr->tx_pause = tp->tx_pause; 39362306a36Sopenharmony_ci spin_unlock_bh(&priv->sta_list_spinlock); 39462306a36Sopenharmony_ci mwifiex_update_ralist_tx_pause(priv, 39562306a36Sopenharmony_ci tp->peermac, 39662306a36Sopenharmony_ci tp->tx_pause); 39762306a36Sopenharmony_ci } else { 39862306a36Sopenharmony_ci spin_unlock_bh(&priv->sta_list_spinlock); 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_civoid mwifiex_process_multi_chan_event(struct mwifiex_private *priv, 40562306a36Sopenharmony_ci struct sk_buff *event_skb) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci struct mwifiex_ie_types_multi_chan_info *chan_info; 40862306a36Sopenharmony_ci struct mwifiex_ie_types_mc_group_info *grp_info; 40962306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 41062306a36Sopenharmony_ci struct mwifiex_ie_types_header *tlv; 41162306a36Sopenharmony_ci u16 tlv_buf_left, tlv_type, tlv_len; 41262306a36Sopenharmony_ci int intf_num, bss_type, bss_num, i; 41362306a36Sopenharmony_ci struct mwifiex_private *intf_priv; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci tlv_buf_left = event_skb->len - sizeof(u32); 41662306a36Sopenharmony_ci chan_info = (void *)event_skb->data + sizeof(u32); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO || 41962306a36Sopenharmony_ci tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) { 42062306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 42162306a36Sopenharmony_ci "unknown TLV in chan_info event\n"); 42262306a36Sopenharmony_ci return; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci adapter->usb_mc_status = le16_to_cpu(chan_info->status); 42662306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n", 42762306a36Sopenharmony_ci adapter->usb_mc_status ? "started" : "over"); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info); 43062306a36Sopenharmony_ci tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { 43362306a36Sopenharmony_ci tlv_type = le16_to_cpu(tlv->type); 43462306a36Sopenharmony_ci tlv_len = le16_to_cpu(tlv->len); 43562306a36Sopenharmony_ci if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) > 43662306a36Sopenharmony_ci tlv_buf_left) { 43762306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t" 43862306a36Sopenharmony_ci "tlvBufLeft=%d\n", tlv_len, tlv_buf_left); 43962306a36Sopenharmony_ci break; 44062306a36Sopenharmony_ci } 44162306a36Sopenharmony_ci if (tlv_type != TLV_TYPE_MC_GROUP_INFO) { 44262306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n", 44362306a36Sopenharmony_ci tlv_type); 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv; 44862306a36Sopenharmony_ci intf_num = grp_info->intf_num; 44962306a36Sopenharmony_ci for (i = 0; i < intf_num; i++) { 45062306a36Sopenharmony_ci bss_type = grp_info->bss_type_numlist[i] >> 4; 45162306a36Sopenharmony_ci bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK; 45262306a36Sopenharmony_ci intf_priv = mwifiex_get_priv_by_id(adapter, bss_num, 45362306a36Sopenharmony_ci bss_type); 45462306a36Sopenharmony_ci if (!intf_priv) { 45562306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 45662306a36Sopenharmony_ci "Invalid bss_type bss_num\t" 45762306a36Sopenharmony_ci "in multi channel event\n"); 45862306a36Sopenharmony_ci continue; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci if (adapter->iface_type == MWIFIEX_USB) { 46162306a36Sopenharmony_ci u8 ep; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci ep = grp_info->hid_num.usb_ep_num; 46462306a36Sopenharmony_ci if (ep == MWIFIEX_USB_EP_DATA || 46562306a36Sopenharmony_ci ep == MWIFIEX_USB_EP_DATA_CH2) 46662306a36Sopenharmony_ci intf_priv->usb_port = ep; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) + 47162306a36Sopenharmony_ci tlv_len; 47262306a36Sopenharmony_ci tlv = (void *)((u8 *)tlv + tlv_len + 47362306a36Sopenharmony_ci sizeof(struct mwifiex_ie_types_header)); 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (adapter->iface_type == MWIFIEX_USB) { 47762306a36Sopenharmony_ci adapter->tx_lock_flag = true; 47862306a36Sopenharmony_ci adapter->usb_mc_setup = true; 47962306a36Sopenharmony_ci mwifiex_multi_chan_resync(adapter); 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_civoid mwifiex_process_tx_pause_event(struct mwifiex_private *priv, 48462306a36Sopenharmony_ci struct sk_buff *event_skb) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci struct mwifiex_ie_types_header *tlv; 48762306a36Sopenharmony_ci u16 tlv_type, tlv_len; 48862306a36Sopenharmony_ci int tlv_buf_left; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (!priv->media_connected) { 49162306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 49262306a36Sopenharmony_ci "tx_pause event while disconnected; bss_role=%d\n", 49362306a36Sopenharmony_ci priv->bss_role); 49462306a36Sopenharmony_ci return; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci tlv_buf_left = event_skb->len - sizeof(u32); 49862306a36Sopenharmony_ci tlv = (void *)event_skb->data + sizeof(u32); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { 50162306a36Sopenharmony_ci tlv_type = le16_to_cpu(tlv->type); 50262306a36Sopenharmony_ci tlv_len = le16_to_cpu(tlv->len); 50362306a36Sopenharmony_ci if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) > 50462306a36Sopenharmony_ci tlv_buf_left) { 50562306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 50662306a36Sopenharmony_ci "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", 50762306a36Sopenharmony_ci tlv_len, tlv_buf_left); 50862306a36Sopenharmony_ci break; 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci if (tlv_type == TLV_TYPE_TX_PAUSE) { 51162306a36Sopenharmony_ci if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) 51262306a36Sopenharmony_ci mwifiex_process_sta_tx_pause(priv, tlv); 51362306a36Sopenharmony_ci else 51462306a36Sopenharmony_ci mwifiex_process_uap_tx_pause(priv, tlv); 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) + 51862306a36Sopenharmony_ci tlv_len; 51962306a36Sopenharmony_ci tlv = (void *)((u8 *)tlv + tlv_len + 52062306a36Sopenharmony_ci sizeof(struct mwifiex_ie_types_header)); 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci/* 52662306a36Sopenharmony_ci* This function handles coex events generated by firmware 52762306a36Sopenharmony_ci*/ 52862306a36Sopenharmony_civoid mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv, 52962306a36Sopenharmony_ci struct sk_buff *event_skb) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 53262306a36Sopenharmony_ci struct mwifiex_ie_types_header *tlv; 53362306a36Sopenharmony_ci struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv; 53462306a36Sopenharmony_ci struct mwifiex_ie_types_btcoex_scan_time *scantlv; 53562306a36Sopenharmony_ci s32 len = event_skb->len - sizeof(u32); 53662306a36Sopenharmony_ci u8 *cur_ptr = event_skb->data + sizeof(u32); 53762306a36Sopenharmony_ci u16 tlv_type, tlv_len; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci while (len >= sizeof(struct mwifiex_ie_types_header)) { 54062306a36Sopenharmony_ci tlv = (struct mwifiex_ie_types_header *)cur_ptr; 54162306a36Sopenharmony_ci tlv_len = le16_to_cpu(tlv->len); 54262306a36Sopenharmony_ci tlv_type = le16_to_cpu(tlv->type); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len) 54562306a36Sopenharmony_ci break; 54662306a36Sopenharmony_ci switch (tlv_type) { 54762306a36Sopenharmony_ci case TLV_BTCOEX_WL_AGGR_WINSIZE: 54862306a36Sopenharmony_ci winsizetlv = 54962306a36Sopenharmony_ci (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv; 55062306a36Sopenharmony_ci adapter->coex_win_size = winsizetlv->coex_win_size; 55162306a36Sopenharmony_ci adapter->coex_tx_win_size = 55262306a36Sopenharmony_ci winsizetlv->tx_win_size; 55362306a36Sopenharmony_ci adapter->coex_rx_win_size = 55462306a36Sopenharmony_ci winsizetlv->rx_win_size; 55562306a36Sopenharmony_ci mwifiex_coex_ampdu_rxwinsize(adapter); 55662306a36Sopenharmony_ci mwifiex_update_ampdu_txwinsize(adapter); 55762306a36Sopenharmony_ci break; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci case TLV_BTCOEX_WL_SCANTIME: 56062306a36Sopenharmony_ci scantlv = 56162306a36Sopenharmony_ci (struct mwifiex_ie_types_btcoex_scan_time *)tlv; 56262306a36Sopenharmony_ci adapter->coex_scan = scantlv->coex_scan; 56362306a36Sopenharmony_ci adapter->coex_min_scan_time = le16_to_cpu(scantlv->min_scan_time); 56462306a36Sopenharmony_ci adapter->coex_max_scan_time = le16_to_cpu(scantlv->max_scan_time); 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci default: 56862306a36Sopenharmony_ci break; 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci len -= tlv_len + sizeof(struct mwifiex_ie_types_header); 57262306a36Sopenharmony_ci cur_ptr += tlv_len + 57362306a36Sopenharmony_ci sizeof(struct mwifiex_ie_types_header); 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n", 57762306a36Sopenharmony_ci adapter->coex_scan, adapter->coex_min_scan_time, 57862306a36Sopenharmony_ci adapter->coex_win_size, adapter->coex_tx_win_size, 57962306a36Sopenharmony_ci adapter->coex_rx_win_size); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic void 58362306a36Sopenharmony_cimwifiex_fw_dump_info_event(struct mwifiex_private *priv, 58462306a36Sopenharmony_ci struct sk_buff *event_skb) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 58762306a36Sopenharmony_ci struct mwifiex_fw_dump_header *fw_dump_hdr = 58862306a36Sopenharmony_ci (void *)adapter->event_body; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (adapter->iface_type != MWIFIEX_USB) { 59162306a36Sopenharmony_ci mwifiex_dbg(adapter, MSG, 59262306a36Sopenharmony_ci "event is not on usb interface, ignore it\n"); 59362306a36Sopenharmony_ci return; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci if (!adapter->devdump_data) { 59762306a36Sopenharmony_ci /* When receive the first event, allocate device dump 59862306a36Sopenharmony_ci * buffer, dump driver info. 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_ci adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE); 60162306a36Sopenharmony_ci if (!adapter->devdump_data) { 60262306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 60362306a36Sopenharmony_ci "vzalloc devdump data failure!\n"); 60462306a36Sopenharmony_ci return; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci mwifiex_drv_info_dump(adapter); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci /* If no proceeded event arrive in 10s, upload device 61062306a36Sopenharmony_ci * dump data, this will be useful if the end of 61162306a36Sopenharmony_ci * transmission event get lost, in this cornel case, 61262306a36Sopenharmony_ci * user would still get partial of the dump. 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ci schedule_delayed_work(&adapter->devdump_work, 61562306a36Sopenharmony_ci msecs_to_jiffies(MWIFIEX_TIMER_10S)); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci /* Overflow check */ 61962306a36Sopenharmony_ci if (adapter->devdump_len + event_skb->len >= MWIFIEX_FW_DUMP_SIZE) 62062306a36Sopenharmony_ci goto upload_dump; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci memmove(adapter->devdump_data + adapter->devdump_len, 62362306a36Sopenharmony_ci adapter->event_skb->data, event_skb->len); 62462306a36Sopenharmony_ci adapter->devdump_len += event_skb->len; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (le16_to_cpu(fw_dump_hdr->type) == FW_DUMP_INFO_ENDED) { 62762306a36Sopenharmony_ci mwifiex_dbg(adapter, MSG, 62862306a36Sopenharmony_ci "receive end of transmission flag event!\n"); 62962306a36Sopenharmony_ci goto upload_dump; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci return; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ciupload_dump: 63462306a36Sopenharmony_ci cancel_delayed_work_sync(&adapter->devdump_work); 63562306a36Sopenharmony_ci mwifiex_upload_device_dump(adapter); 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci/* 63962306a36Sopenharmony_ci * This function handles events generated by firmware. 64062306a36Sopenharmony_ci * 64162306a36Sopenharmony_ci * This is a generic function and handles all events. 64262306a36Sopenharmony_ci * 64362306a36Sopenharmony_ci * Event specific routines are called by this function based 64462306a36Sopenharmony_ci * upon the generated event cause. 64562306a36Sopenharmony_ci * 64662306a36Sopenharmony_ci * For the following events, the function just forwards them to upper 64762306a36Sopenharmony_ci * layers, optionally recording the change - 64862306a36Sopenharmony_ci * - EVENT_LINK_SENSED 64962306a36Sopenharmony_ci * - EVENT_MIC_ERR_UNICAST 65062306a36Sopenharmony_ci * - EVENT_MIC_ERR_MULTICAST 65162306a36Sopenharmony_ci * - EVENT_PORT_RELEASE 65262306a36Sopenharmony_ci * - EVENT_RSSI_LOW 65362306a36Sopenharmony_ci * - EVENT_SNR_LOW 65462306a36Sopenharmony_ci * - EVENT_MAX_FAIL 65562306a36Sopenharmony_ci * - EVENT_RSSI_HIGH 65662306a36Sopenharmony_ci * - EVENT_SNR_HIGH 65762306a36Sopenharmony_ci * - EVENT_DATA_RSSI_LOW 65862306a36Sopenharmony_ci * - EVENT_DATA_SNR_LOW 65962306a36Sopenharmony_ci * - EVENT_DATA_RSSI_HIGH 66062306a36Sopenharmony_ci * - EVENT_DATA_SNR_HIGH 66162306a36Sopenharmony_ci * - EVENT_LINK_QUALITY 66262306a36Sopenharmony_ci * - EVENT_PRE_BEACON_LOST 66362306a36Sopenharmony_ci * - EVENT_IBSS_COALESCED 66462306a36Sopenharmony_ci * - EVENT_IBSS_STA_CONNECT 66562306a36Sopenharmony_ci * - EVENT_IBSS_STA_DISCONNECT 66662306a36Sopenharmony_ci * - EVENT_WEP_ICV_ERR 66762306a36Sopenharmony_ci * - EVENT_BW_CHANGE 66862306a36Sopenharmony_ci * - EVENT_HOSTWAKE_STAIE 66962306a36Sopenharmony_ci * 67062306a36Sopenharmony_ci * For the following events, no action is taken - 67162306a36Sopenharmony_ci * - EVENT_MIB_CHANGED 67262306a36Sopenharmony_ci * - EVENT_INIT_DONE 67362306a36Sopenharmony_ci * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL 67462306a36Sopenharmony_ci * 67562306a36Sopenharmony_ci * Rest of the supported events requires driver handling - 67662306a36Sopenharmony_ci * - EVENT_DEAUTHENTICATED 67762306a36Sopenharmony_ci * - EVENT_DISASSOCIATED 67862306a36Sopenharmony_ci * - EVENT_LINK_LOST 67962306a36Sopenharmony_ci * - EVENT_PS_SLEEP 68062306a36Sopenharmony_ci * - EVENT_PS_AWAKE 68162306a36Sopenharmony_ci * - EVENT_DEEP_SLEEP_AWAKE 68262306a36Sopenharmony_ci * - EVENT_HS_ACT_REQ 68362306a36Sopenharmony_ci * - EVENT_ADHOC_BCN_LOST 68462306a36Sopenharmony_ci * - EVENT_BG_SCAN_REPORT 68562306a36Sopenharmony_ci * - EVENT_WMM_STATUS_CHANGE 68662306a36Sopenharmony_ci * - EVENT_ADDBA 68762306a36Sopenharmony_ci * - EVENT_DELBA 68862306a36Sopenharmony_ci * - EVENT_BA_STREAM_TIEMOUT 68962306a36Sopenharmony_ci * - EVENT_AMSDU_AGGR_CTRL 69062306a36Sopenharmony_ci * - EVENT_FW_DUMP_INFO 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_ciint mwifiex_process_sta_event(struct mwifiex_private *priv) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 69562306a36Sopenharmony_ci int ret = 0, i; 69662306a36Sopenharmony_ci u32 eventcause = adapter->event_cause; 69762306a36Sopenharmony_ci u16 ctrl, reason_code; 69862306a36Sopenharmony_ci u8 ibss_sta_addr[ETH_ALEN]; 69962306a36Sopenharmony_ci struct mwifiex_sta_node *sta_ptr; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci switch (eventcause) { 70262306a36Sopenharmony_ci case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: 70362306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 70462306a36Sopenharmony_ci "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n"); 70562306a36Sopenharmony_ci break; 70662306a36Sopenharmony_ci case EVENT_LINK_SENSED: 70762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: LINK_SENSED\n"); 70862306a36Sopenharmony_ci if (!netif_carrier_ok(priv->netdev)) 70962306a36Sopenharmony_ci netif_carrier_on(priv->netdev); 71062306a36Sopenharmony_ci mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 71162306a36Sopenharmony_ci break; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci case EVENT_DEAUTHENTICATED: 71462306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Deauthenticated\n"); 71562306a36Sopenharmony_ci if (priv->wps.session_enable) { 71662306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 71762306a36Sopenharmony_ci "info: receive deauth event in wps session\n"); 71862306a36Sopenharmony_ci break; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci adapter->dbg.num_event_deauth++; 72162306a36Sopenharmony_ci if (priv->media_connected) { 72262306a36Sopenharmony_ci reason_code = 72362306a36Sopenharmony_ci get_unaligned_le16(adapter->event_body); 72462306a36Sopenharmony_ci mwifiex_reset_connect_state(priv, reason_code, true); 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci break; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci case EVENT_DISASSOCIATED: 72962306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Disassociated\n"); 73062306a36Sopenharmony_ci if (priv->wps.session_enable) { 73162306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 73262306a36Sopenharmony_ci "info: receive disassoc event in wps session\n"); 73362306a36Sopenharmony_ci break; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci adapter->dbg.num_event_disassoc++; 73662306a36Sopenharmony_ci if (priv->media_connected) { 73762306a36Sopenharmony_ci reason_code = 73862306a36Sopenharmony_ci get_unaligned_le16(adapter->event_body); 73962306a36Sopenharmony_ci mwifiex_reset_connect_state(priv, reason_code, true); 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci break; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci case EVENT_LINK_LOST: 74462306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Link lost\n"); 74562306a36Sopenharmony_ci adapter->dbg.num_event_link_lost++; 74662306a36Sopenharmony_ci if (priv->media_connected) { 74762306a36Sopenharmony_ci reason_code = 74862306a36Sopenharmony_ci get_unaligned_le16(adapter->event_body); 74962306a36Sopenharmony_ci mwifiex_reset_connect_state(priv, reason_code, true); 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci break; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci case EVENT_PS_SLEEP: 75462306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n"); 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci adapter->ps_state = PS_STATE_PRE_SLEEP; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci mwifiex_check_ps_cond(adapter); 75962306a36Sopenharmony_ci break; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci case EVENT_PS_AWAKE: 76262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n"); 76362306a36Sopenharmony_ci if (!adapter->pps_uapsd_mode && 76462306a36Sopenharmony_ci (priv->port_open || 76562306a36Sopenharmony_ci (priv->bss_mode == NL80211_IFTYPE_ADHOC)) && 76662306a36Sopenharmony_ci priv->media_connected && adapter->sleep_period.period) { 76762306a36Sopenharmony_ci adapter->pps_uapsd_mode = true; 76862306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, 76962306a36Sopenharmony_ci "event: PPS/UAPSD mode activated\n"); 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci adapter->tx_lock_flag = false; 77262306a36Sopenharmony_ci if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { 77362306a36Sopenharmony_ci if (mwifiex_check_last_packet_indication(priv)) { 77462306a36Sopenharmony_ci if (adapter->data_sent || 77562306a36Sopenharmony_ci (adapter->if_ops.is_port_ready && 77662306a36Sopenharmony_ci !adapter->if_ops.is_port_ready(priv))) { 77762306a36Sopenharmony_ci adapter->ps_state = PS_STATE_AWAKE; 77862306a36Sopenharmony_ci adapter->pm_wakeup_card_req = false; 77962306a36Sopenharmony_ci adapter->pm_wakeup_fw_try = false; 78062306a36Sopenharmony_ci del_timer(&adapter->wakeup_timer); 78162306a36Sopenharmony_ci break; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci if (!mwifiex_send_null_packet 78462306a36Sopenharmony_ci (priv, 78562306a36Sopenharmony_ci MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | 78662306a36Sopenharmony_ci MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) 78762306a36Sopenharmony_ci adapter->ps_state = 78862306a36Sopenharmony_ci PS_STATE_SLEEP; 78962306a36Sopenharmony_ci return 0; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci adapter->ps_state = PS_STATE_AWAKE; 79362306a36Sopenharmony_ci adapter->pm_wakeup_card_req = false; 79462306a36Sopenharmony_ci adapter->pm_wakeup_fw_try = false; 79562306a36Sopenharmony_ci del_timer(&adapter->wakeup_timer); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci break; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci case EVENT_DEEP_SLEEP_AWAKE: 80062306a36Sopenharmony_ci adapter->if_ops.wakeup_complete(adapter); 80162306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: DS_AWAKE\n"); 80262306a36Sopenharmony_ci if (adapter->is_deep_sleep) 80362306a36Sopenharmony_ci adapter->is_deep_sleep = false; 80462306a36Sopenharmony_ci break; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci case EVENT_HS_ACT_REQ: 80762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: HS_ACT_REQ\n"); 80862306a36Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, 80962306a36Sopenharmony_ci 0, 0, NULL, false); 81062306a36Sopenharmony_ci break; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci case EVENT_MIC_ERR_UNICAST: 81362306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: UNICAST MIC ERROR\n"); 81462306a36Sopenharmony_ci cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, 81562306a36Sopenharmony_ci NL80211_KEYTYPE_PAIRWISE, 81662306a36Sopenharmony_ci -1, NULL, GFP_KERNEL); 81762306a36Sopenharmony_ci break; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci case EVENT_MIC_ERR_MULTICAST: 82062306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: MULTICAST MIC ERROR\n"); 82162306a36Sopenharmony_ci cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, 82262306a36Sopenharmony_ci NL80211_KEYTYPE_GROUP, 82362306a36Sopenharmony_ci -1, NULL, GFP_KERNEL); 82462306a36Sopenharmony_ci break; 82562306a36Sopenharmony_ci case EVENT_MIB_CHANGED: 82662306a36Sopenharmony_ci case EVENT_INIT_DONE: 82762306a36Sopenharmony_ci break; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci case EVENT_ADHOC_BCN_LOST: 83062306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n"); 83162306a36Sopenharmony_ci priv->adhoc_is_link_sensed = false; 83262306a36Sopenharmony_ci mwifiex_clean_txrx(priv); 83362306a36Sopenharmony_ci mwifiex_stop_net_dev_queue(priv->netdev, adapter); 83462306a36Sopenharmony_ci if (netif_carrier_ok(priv->netdev)) 83562306a36Sopenharmony_ci netif_carrier_off(priv->netdev); 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci case EVENT_BG_SCAN_REPORT: 83962306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: BGS_REPORT\n"); 84062306a36Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY, 84162306a36Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, false); 84262306a36Sopenharmony_ci break; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci case EVENT_BG_SCAN_STOPPED: 84562306a36Sopenharmony_ci dev_dbg(adapter->dev, "event: BGS_STOPPED\n"); 84662306a36Sopenharmony_ci cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0); 84762306a36Sopenharmony_ci if (priv->sched_scanning) 84862306a36Sopenharmony_ci priv->sched_scanning = false; 84962306a36Sopenharmony_ci break; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci case EVENT_PORT_RELEASE: 85262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n"); 85362306a36Sopenharmony_ci priv->port_open = true; 85462306a36Sopenharmony_ci break; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci case EVENT_EXT_SCAN_REPORT: 85762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n"); 85862306a36Sopenharmony_ci /* We intend to skip this event during suspend, but handle 85962306a36Sopenharmony_ci * it in interface disabled case 86062306a36Sopenharmony_ci */ 86162306a36Sopenharmony_ci if (adapter->ext_scan && (!priv->scan_aborting || 86262306a36Sopenharmony_ci !netif_running(priv->netdev))) 86362306a36Sopenharmony_ci ret = mwifiex_handle_event_ext_scan_report(priv, 86462306a36Sopenharmony_ci adapter->event_skb->data); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci break; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci case EVENT_WMM_STATUS_CHANGE: 86962306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: WMM status changed\n"); 87062306a36Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 87162306a36Sopenharmony_ci 0, 0, NULL, false); 87262306a36Sopenharmony_ci break; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci case EVENT_RSSI_LOW: 87562306a36Sopenharmony_ci cfg80211_cqm_rssi_notify(priv->netdev, 87662306a36Sopenharmony_ci NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, 87762306a36Sopenharmony_ci 0, GFP_KERNEL); 87862306a36Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, 87962306a36Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, false); 88062306a36Sopenharmony_ci priv->subsc_evt_rssi_state = RSSI_LOW_RECVD; 88162306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_LOW\n"); 88262306a36Sopenharmony_ci break; 88362306a36Sopenharmony_ci case EVENT_SNR_LOW: 88462306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_LOW\n"); 88562306a36Sopenharmony_ci break; 88662306a36Sopenharmony_ci case EVENT_MAX_FAIL: 88762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: MAX_FAIL\n"); 88862306a36Sopenharmony_ci break; 88962306a36Sopenharmony_ci case EVENT_RSSI_HIGH: 89062306a36Sopenharmony_ci cfg80211_cqm_rssi_notify(priv->netdev, 89162306a36Sopenharmony_ci NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, 89262306a36Sopenharmony_ci 0, GFP_KERNEL); 89362306a36Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, 89462306a36Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, false); 89562306a36Sopenharmony_ci priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD; 89662306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_HIGH\n"); 89762306a36Sopenharmony_ci break; 89862306a36Sopenharmony_ci case EVENT_SNR_HIGH: 89962306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_HIGH\n"); 90062306a36Sopenharmony_ci break; 90162306a36Sopenharmony_ci case EVENT_DATA_RSSI_LOW: 90262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Data RSSI_LOW\n"); 90362306a36Sopenharmony_ci break; 90462306a36Sopenharmony_ci case EVENT_DATA_SNR_LOW: 90562306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Data SNR_LOW\n"); 90662306a36Sopenharmony_ci break; 90762306a36Sopenharmony_ci case EVENT_DATA_RSSI_HIGH: 90862306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Data RSSI_HIGH\n"); 90962306a36Sopenharmony_ci break; 91062306a36Sopenharmony_ci case EVENT_DATA_SNR_HIGH: 91162306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Data SNR_HIGH\n"); 91262306a36Sopenharmony_ci break; 91362306a36Sopenharmony_ci case EVENT_LINK_QUALITY: 91462306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Link Quality\n"); 91562306a36Sopenharmony_ci break; 91662306a36Sopenharmony_ci case EVENT_PRE_BEACON_LOST: 91762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Pre-Beacon Lost\n"); 91862306a36Sopenharmony_ci break; 91962306a36Sopenharmony_ci case EVENT_IBSS_COALESCED: 92062306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: IBSS_COALESCED\n"); 92162306a36Sopenharmony_ci ret = mwifiex_send_cmd(priv, 92262306a36Sopenharmony_ci HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, 92362306a36Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, false); 92462306a36Sopenharmony_ci break; 92562306a36Sopenharmony_ci case EVENT_IBSS_STA_CONNECT: 92662306a36Sopenharmony_ci ether_addr_copy(ibss_sta_addr, adapter->event_body + 2); 92762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: IBSS_STA_CONNECT %pM\n", 92862306a36Sopenharmony_ci ibss_sta_addr); 92962306a36Sopenharmony_ci sta_ptr = mwifiex_add_sta_entry(priv, ibss_sta_addr); 93062306a36Sopenharmony_ci if (sta_ptr && adapter->adhoc_11n_enabled) { 93162306a36Sopenharmony_ci mwifiex_check_ibss_peer_capabilities(priv, sta_ptr, 93262306a36Sopenharmony_ci adapter->event_skb); 93362306a36Sopenharmony_ci if (sta_ptr->is_11n_enabled) 93462306a36Sopenharmony_ci for (i = 0; i < MAX_NUM_TID; i++) 93562306a36Sopenharmony_ci sta_ptr->ampdu_sta[i] = 93662306a36Sopenharmony_ci priv->aggr_prio_tbl[i].ampdu_user; 93762306a36Sopenharmony_ci else 93862306a36Sopenharmony_ci for (i = 0; i < MAX_NUM_TID; i++) 93962306a36Sopenharmony_ci sta_ptr->ampdu_sta[i] = 94062306a36Sopenharmony_ci BA_STREAM_NOT_ALLOWED; 94162306a36Sopenharmony_ci memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); 94262306a36Sopenharmony_ci } 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci break; 94562306a36Sopenharmony_ci case EVENT_IBSS_STA_DISCONNECT: 94662306a36Sopenharmony_ci ether_addr_copy(ibss_sta_addr, adapter->event_body + 2); 94762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: IBSS_STA_DISCONNECT %pM\n", 94862306a36Sopenharmony_ci ibss_sta_addr); 94962306a36Sopenharmony_ci sta_ptr = mwifiex_get_sta_entry(priv, ibss_sta_addr); 95062306a36Sopenharmony_ci if (sta_ptr && sta_ptr->is_11n_enabled) { 95162306a36Sopenharmony_ci mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, 95262306a36Sopenharmony_ci ibss_sta_addr); 95362306a36Sopenharmony_ci mwifiex_del_tx_ba_stream_tbl_by_ra(priv, ibss_sta_addr); 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci mwifiex_wmm_del_peer_ra_list(priv, ibss_sta_addr); 95662306a36Sopenharmony_ci mwifiex_del_sta_entry(priv, ibss_sta_addr); 95762306a36Sopenharmony_ci break; 95862306a36Sopenharmony_ci case EVENT_ADDBA: 95962306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n"); 96062306a36Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, 96162306a36Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 96262306a36Sopenharmony_ci adapter->event_body, false); 96362306a36Sopenharmony_ci break; 96462306a36Sopenharmony_ci case EVENT_DELBA: 96562306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n"); 96662306a36Sopenharmony_ci mwifiex_11n_delete_ba_stream(priv, adapter->event_body); 96762306a36Sopenharmony_ci break; 96862306a36Sopenharmony_ci case EVENT_BA_STREAM_TIEMOUT: 96962306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: BA Stream timeout\n"); 97062306a36Sopenharmony_ci mwifiex_11n_ba_stream_timeout(priv, 97162306a36Sopenharmony_ci (struct host_cmd_ds_11n_batimeout 97262306a36Sopenharmony_ci *) 97362306a36Sopenharmony_ci adapter->event_body); 97462306a36Sopenharmony_ci break; 97562306a36Sopenharmony_ci case EVENT_AMSDU_AGGR_CTRL: 97662306a36Sopenharmony_ci ctrl = get_unaligned_le16(adapter->event_body); 97762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, 97862306a36Sopenharmony_ci "event: AMSDU_AGGR_CTRL %d\n", ctrl); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci adapter->tx_buf_size = 98162306a36Sopenharmony_ci min_t(u16, adapter->curr_tx_buf_size, ctrl); 98262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: tx_buf_size %d\n", 98362306a36Sopenharmony_ci adapter->tx_buf_size); 98462306a36Sopenharmony_ci break; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci case EVENT_WEP_ICV_ERR: 98762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: WEP ICV error\n"); 98862306a36Sopenharmony_ci break; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci case EVENT_BW_CHANGE: 99162306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: BW Change\n"); 99262306a36Sopenharmony_ci break; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci case EVENT_HOSTWAKE_STAIE: 99562306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, 99662306a36Sopenharmony_ci "event: HOSTWAKE_STAIE %d\n", eventcause); 99762306a36Sopenharmony_ci break; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci case EVENT_REMAIN_ON_CHAN_EXPIRED: 100062306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, 100162306a36Sopenharmony_ci "event: Remain on channel expired\n"); 100262306a36Sopenharmony_ci cfg80211_remain_on_channel_expired(&priv->wdev, 100362306a36Sopenharmony_ci priv->roc_cfg.cookie, 100462306a36Sopenharmony_ci &priv->roc_cfg.chan, 100562306a36Sopenharmony_ci GFP_ATOMIC); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg)); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci break; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci case EVENT_CHANNEL_SWITCH_ANN: 101262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Channel Switch Announcement\n"); 101362306a36Sopenharmony_ci priv->csa_expire_time = 101462306a36Sopenharmony_ci jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME); 101562306a36Sopenharmony_ci priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel; 101662306a36Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, 101762306a36Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 101862306a36Sopenharmony_ci priv->curr_bss_params.bss_descriptor.mac_address, 101962306a36Sopenharmony_ci false); 102062306a36Sopenharmony_ci break; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci case EVENT_TDLS_GENERIC_EVENT: 102362306a36Sopenharmony_ci ret = mwifiex_parse_tdls_event(priv, adapter->event_skb); 102462306a36Sopenharmony_ci break; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci case EVENT_TX_DATA_PAUSE: 102762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n"); 102862306a36Sopenharmony_ci mwifiex_process_tx_pause_event(priv, adapter->event_skb); 102962306a36Sopenharmony_ci break; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci case EVENT_MULTI_CHAN_INFO: 103262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n"); 103362306a36Sopenharmony_ci mwifiex_process_multi_chan_event(priv, adapter->event_skb); 103462306a36Sopenharmony_ci break; 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci case EVENT_TX_STATUS_REPORT: 103762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n"); 103862306a36Sopenharmony_ci mwifiex_parse_tx_status_event(priv, adapter->event_body); 103962306a36Sopenharmony_ci break; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci case EVENT_CHANNEL_REPORT_RDY: 104262306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Channel Report\n"); 104362306a36Sopenharmony_ci ret = mwifiex_11h_handle_chanrpt_ready(priv, 104462306a36Sopenharmony_ci adapter->event_skb); 104562306a36Sopenharmony_ci break; 104662306a36Sopenharmony_ci case EVENT_RADAR_DETECTED: 104762306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: Radar detected\n"); 104862306a36Sopenharmony_ci ret = mwifiex_11h_handle_radar_detected(priv, 104962306a36Sopenharmony_ci adapter->event_skb); 105062306a36Sopenharmony_ci break; 105162306a36Sopenharmony_ci case EVENT_BT_COEX_WLAN_PARA_CHANGE: 105262306a36Sopenharmony_ci dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n"); 105362306a36Sopenharmony_ci if (adapter->ignore_btcoex_events) 105462306a36Sopenharmony_ci break; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci mwifiex_bt_coex_wlan_param_update_event(priv, 105762306a36Sopenharmony_ci adapter->event_skb); 105862306a36Sopenharmony_ci break; 105962306a36Sopenharmony_ci case EVENT_RXBA_SYNC: 106062306a36Sopenharmony_ci dev_dbg(adapter->dev, "EVENT: RXBA_SYNC\n"); 106162306a36Sopenharmony_ci mwifiex_11n_rxba_sync_event(priv, adapter->event_body, 106262306a36Sopenharmony_ci adapter->event_skb->len - 106362306a36Sopenharmony_ci sizeof(eventcause)); 106462306a36Sopenharmony_ci break; 106562306a36Sopenharmony_ci case EVENT_FW_DUMP_INFO: 106662306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: firmware debug info\n"); 106762306a36Sopenharmony_ci mwifiex_fw_dump_info_event(priv, adapter->event_skb); 106862306a36Sopenharmony_ci break; 106962306a36Sopenharmony_ci /* Debugging event; not used, but let's not print an ERROR for it. */ 107062306a36Sopenharmony_ci case EVENT_UNKNOWN_DEBUG: 107162306a36Sopenharmony_ci mwifiex_dbg(adapter, EVENT, "event: debug\n"); 107262306a36Sopenharmony_ci break; 107362306a36Sopenharmony_ci default: 107462306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n", 107562306a36Sopenharmony_ci eventcause); 107662306a36Sopenharmony_ci break; 107762306a36Sopenharmony_ci } 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci return ret; 108062306a36Sopenharmony_ci} 1081