1/* 2 * Marvell Wireless LAN device driver: AP event handling 3 * 4 * Copyright (C) 2012-2014, 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 "main.h" 22#include "11n.h" 23 24 25 26 27/* 28 * This function handles AP interface specific events generated by firmware. 29 * 30 * Event specific routines are called by this function based 31 * upon the generated event cause. 32 * 33 * 34 * Events supported for AP - 35 * - EVENT_UAP_STA_ASSOC 36 * - EVENT_UAP_STA_DEAUTH 37 * - EVENT_UAP_BSS_ACTIVE 38 * - EVENT_UAP_BSS_START 39 * - EVENT_UAP_BSS_IDLE 40 * - EVENT_UAP_MIC_COUNTERMEASURES: 41 */ 42int mwifiex_process_uap_event(struct mwifiex_private *priv) 43{ 44 struct mwifiex_adapter *adapter = priv->adapter; 45 int len, i; 46 u32 eventcause = adapter->event_cause; 47 struct station_info sinfo; 48 struct mwifiex_assoc_event *event; 49 struct mwifiex_sta_node *node; 50 u8 *deauth_mac; 51 struct host_cmd_ds_11n_batimeout *ba_timeout; 52 u16 ctrl; 53 54 switch (eventcause) { 55 case EVENT_UAP_STA_ASSOC: 56 memset(&sinfo, 0, sizeof(sinfo)); 57 event = (struct mwifiex_assoc_event *) 58 (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER); 59 if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { 60 len = -1; 61 62 if (ieee80211_is_assoc_req(event->frame_control)) 63 len = 0; 64 else if (ieee80211_is_reassoc_req(event->frame_control)) 65 /* There will be ETH_ALEN bytes of 66 * current_ap_addr before the re-assoc ies. 67 */ 68 len = ETH_ALEN; 69 70 if (len != -1) { 71 sinfo.assoc_req_ies = &event->data[len]; 72 len = (u8 *)sinfo.assoc_req_ies - 73 (u8 *)&event->frame_control; 74 sinfo.assoc_req_ies_len = 75 le16_to_cpu(event->len) - (u16)len; 76 } 77 } 78 cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, 79 GFP_KERNEL); 80 81 node = mwifiex_add_sta_entry(priv, event->sta_addr); 82 if (!node) { 83 dev_warn(adapter->dev, 84 "could not create station entry!\n"); 85 return -1; 86 } 87 88 if (!priv->ap_11n_enabled) 89 break; 90 91 mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies, 92 sinfo.assoc_req_ies_len, node); 93 94 for (i = 0; i < MAX_NUM_TID; i++) { 95 if (node->is_11n_enabled) 96 node->ampdu_sta[i] = 97 priv->aggr_prio_tbl[i].ampdu_user; 98 else 99 node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; 100 } 101 memset(node->rx_seq, 0xff, sizeof(node->rx_seq)); 102 break; 103 case EVENT_UAP_STA_DEAUTH: 104 deauth_mac = adapter->event_body + 105 MWIFIEX_UAP_EVENT_EXTRA_HEADER; 106 cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL); 107 108 if (priv->ap_11n_enabled) { 109 mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac); 110 mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac); 111 } 112 mwifiex_wmm_del_peer_ra_list(priv, deauth_mac); 113 mwifiex_del_sta_entry(priv, deauth_mac); 114 break; 115 case EVENT_UAP_BSS_IDLE: 116 priv->media_connected = false; 117 if (netif_carrier_ok(priv->netdev)) 118 netif_carrier_off(priv->netdev); 119 mwifiex_stop_net_dev_queue(priv->netdev, adapter); 120 121 mwifiex_clean_txrx(priv); 122 mwifiex_del_all_sta_list(priv); 123 break; 124 case EVENT_UAP_BSS_ACTIVE: 125 priv->media_connected = true; 126 if (!netif_carrier_ok(priv->netdev)) 127 netif_carrier_on(priv->netdev); 128 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 129 break; 130 case EVENT_UAP_BSS_START: 131 dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); 132 memcpy(priv->netdev->dev_addr, adapter->event_body + 2, 133 ETH_ALEN); 134 if (priv->hist_data) 135 mwifiex_hist_data_reset(priv); 136 break; 137 case EVENT_UAP_MIC_COUNTERMEASURES: 138 /* For future development */ 139 dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); 140 break; 141 case EVENT_AMSDU_AGGR_CTRL: 142 ctrl = le16_to_cpu(*(__le16 *)adapter->event_body); 143 dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl); 144 145 if (priv->media_connected) { 146 adapter->tx_buf_size = 147 min_t(u16, adapter->curr_tx_buf_size, ctrl); 148 dev_dbg(adapter->dev, "event: tx_buf_size %d\n", 149 adapter->tx_buf_size); 150 } 151 break; 152 case EVENT_ADDBA: 153 dev_dbg(adapter->dev, "event: ADDBA Request\n"); 154 if (priv->media_connected) 155 mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, 156 HostCmd_ACT_GEN_SET, 0, 157 adapter->event_body, false); 158 break; 159 case EVENT_DELBA: 160 dev_dbg(adapter->dev, "event: DELBA Request\n"); 161 if (priv->media_connected) 162 mwifiex_11n_delete_ba_stream(priv, adapter->event_body); 163 break; 164 case EVENT_BA_STREAM_TIEMOUT: 165 dev_dbg(adapter->dev, "event: BA Stream timeout\n"); 166 if (priv->media_connected) { 167 ba_timeout = (void *)adapter->event_body; 168 mwifiex_11n_ba_stream_timeout(priv, ba_timeout); 169 } 170 break; 171 case EVENT_EXT_SCAN_REPORT: 172 dev_dbg(adapter->dev, "event: EXT_SCAN Report\n"); 173 if (adapter->ext_scan) 174 return mwifiex_handle_event_ext_scan_report(priv, 175 adapter->event_skb->data); 176 break; 177 case EVENT_TX_STATUS_REPORT: 178 dev_dbg(adapter->dev, "event: TX_STATUS Report\n"); 179 mwifiex_parse_tx_status_event(priv, adapter->event_body); 180 break; 181 case EVENT_PS_SLEEP: 182 dev_dbg(adapter->dev, "info: EVENT: SLEEP\n"); 183 184 adapter->ps_state = PS_STATE_PRE_SLEEP; 185 186 mwifiex_check_ps_cond(adapter); 187 break; 188 189 case EVENT_PS_AWAKE: 190 dev_dbg(adapter->dev, "info: EVENT: AWAKE\n"); 191 if (!adapter->pps_uapsd_mode && 192 priv->media_connected && adapter->sleep_period.period) { 193 adapter->pps_uapsd_mode = true; 194 dev_dbg(adapter->dev, 195 "event: PPS/UAPSD mode activated\n"); 196 } 197 adapter->tx_lock_flag = false; 198 if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { 199 if (mwifiex_check_last_packet_indication(priv)) { 200 if (adapter->data_sent) { 201 adapter->ps_state = PS_STATE_AWAKE; 202 adapter->pm_wakeup_card_req = false; 203 adapter->pm_wakeup_fw_try = false; 204 break; 205 } 206 if (!mwifiex_send_null_packet 207 (priv, 208 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | 209 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) 210 adapter->ps_state = 211 PS_STATE_SLEEP; 212 return 0; 213 } 214 } 215 adapter->ps_state = PS_STATE_AWAKE; 216 adapter->pm_wakeup_card_req = false; 217 adapter->pm_wakeup_fw_try = false; 218 break; 219 220 case EVENT_CHANNEL_REPORT_RDY: 221 dev_dbg(adapter->dev, "event: Channel Report\n"); 222 mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb); 223 break; 224 case EVENT_RADAR_DETECTED: 225 dev_dbg(adapter->dev, "event: Radar detected\n"); 226 mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); 227 break; 228 default: 229 dev_dbg(adapter->dev, "event: unknown event id: %#x\n", 230 eventcause); 231 break; 232 } 233 234 return 0; 235} 236 237/* This function deletes station entry from associated station list. 238 * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream 239 * tables created for this station are deleted. 240 */ 241void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, 242 struct mwifiex_sta_node *node) 243{ 244 if (priv->ap_11n_enabled && node->is_11n_enabled) { 245 mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr); 246 mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr); 247 } 248 mwifiex_del_sta_entry(priv, node->mac_addr); 249 250 return; 251} 252