root/drivers/net/wireless/marvell/mwifiex/uap_event.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mwifiex_check_uap_capabilities
  2. mwifiex_process_uap_event
  3. mwifiex_uap_del_sta_data

   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 #define MWIFIEX_BSS_START_EVT_FIX_SIZE    12
  25 
  26 static int mwifiex_check_uap_capabilities(struct mwifiex_private *priv,
  27                                           struct sk_buff *event)
  28 {
  29         int evt_len;
  30         u8 *curr;
  31         u16 tlv_len;
  32         struct mwifiex_ie_types_data *tlv_hdr;
  33         struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
  34         int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
  35 
  36         priv->wmm_enabled = false;
  37         skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
  38         evt_len = event->len;
  39         curr = event->data;
  40 
  41         mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilities:",
  42                          event->data, event->len);
  43 
  44         skb_push(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
  45 
  46         while ((evt_len >= sizeof(tlv_hdr->header))) {
  47                 tlv_hdr = (struct mwifiex_ie_types_data *)curr;
  48                 tlv_len = le16_to_cpu(tlv_hdr->header.len);
  49 
  50                 if (evt_len < tlv_len + sizeof(tlv_hdr->header))
  51                         break;
  52 
  53                 switch (le16_to_cpu(tlv_hdr->header.type)) {
  54                 case WLAN_EID_HT_CAPABILITY:
  55                         priv->ap_11n_enabled = true;
  56                         break;
  57 
  58                 case WLAN_EID_VHT_CAPABILITY:
  59                         priv->ap_11ac_enabled = true;
  60                         break;
  61 
  62                 case WLAN_EID_VENDOR_SPECIFIC:
  63                         /* Point the regular IEEE IE 2 bytes into the Marvell IE
  64                          * and setup the IEEE IE type and length byte fields
  65                          */
  66                         wmm_param_ie = (void *)(curr + 2);
  67                         wmm_param_ie->vend_hdr.len = (u8)tlv_len;
  68                         wmm_param_ie->vend_hdr.element_id =
  69                                                 WLAN_EID_VENDOR_SPECIFIC;
  70                         mwifiex_dbg(priv->adapter, EVENT,
  71                                     "info: check uap capabilities:\t"
  72                                     "wmm parameter set count: %d\n",
  73                                     wmm_param_ie->qos_info_bitmap & mask);
  74 
  75                         mwifiex_wmm_setup_ac_downgrade(priv);
  76                         priv->wmm_enabled = true;
  77                         mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
  78                         break;
  79 
  80                 default:
  81                         break;
  82                 }
  83 
  84                 curr += (tlv_len + sizeof(tlv_hdr->header));
  85                 evt_len -= (tlv_len + sizeof(tlv_hdr->header));
  86         }
  87 
  88         return 0;
  89 }
  90 
  91 /*
  92  * This function handles AP interface specific events generated by firmware.
  93  *
  94  * Event specific routines are called by this function based
  95  * upon the generated event cause.
  96  *
  97  *
  98  * Events supported for AP -
  99  *      - EVENT_UAP_STA_ASSOC
 100  *      - EVENT_UAP_STA_DEAUTH
 101  *      - EVENT_UAP_BSS_ACTIVE
 102  *      - EVENT_UAP_BSS_START
 103  *      - EVENT_UAP_BSS_IDLE
 104  *      - EVENT_UAP_MIC_COUNTERMEASURES:
 105  */
 106 int mwifiex_process_uap_event(struct mwifiex_private *priv)
 107 {
 108         struct mwifiex_adapter *adapter = priv->adapter;
 109         int len, i;
 110         u32 eventcause = adapter->event_cause;
 111         struct station_info *sinfo;
 112         struct mwifiex_assoc_event *event;
 113         struct mwifiex_sta_node *node;
 114         u8 *deauth_mac;
 115         struct host_cmd_ds_11n_batimeout *ba_timeout;
 116         u16 ctrl;
 117 
 118         switch (eventcause) {
 119         case EVENT_UAP_STA_ASSOC:
 120                 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
 121                 if (!sinfo)
 122                         return -ENOMEM;
 123 
 124                 event = (struct mwifiex_assoc_event *)
 125                         (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
 126                 if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
 127                         len = -1;
 128 
 129                         if (ieee80211_is_assoc_req(event->frame_control))
 130                                 len = 0;
 131                         else if (ieee80211_is_reassoc_req(event->frame_control))
 132                                 /* There will be ETH_ALEN bytes of
 133                                  * current_ap_addr before the re-assoc ies.
 134                                  */
 135                                 len = ETH_ALEN;
 136 
 137                         if (len != -1) {
 138                                 sinfo->assoc_req_ies = &event->data[len];
 139                                 len = (u8 *)sinfo->assoc_req_ies -
 140                                       (u8 *)&event->frame_control;
 141                                 sinfo->assoc_req_ies_len =
 142                                         le16_to_cpu(event->len) - (u16)len;
 143                         }
 144                 }
 145                 cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo,
 146                                  GFP_KERNEL);
 147 
 148                 node = mwifiex_add_sta_entry(priv, event->sta_addr);
 149                 if (!node) {
 150                         mwifiex_dbg(adapter, ERROR,
 151                                     "could not create station entry!\n");
 152                         kfree(sinfo);
 153                         return -1;
 154                 }
 155 
 156                 if (!priv->ap_11n_enabled) {
 157                         kfree(sinfo);
 158                         break;
 159                 }
 160 
 161                 mwifiex_set_sta_ht_cap(priv, sinfo->assoc_req_ies,
 162                                        sinfo->assoc_req_ies_len, node);
 163 
 164                 for (i = 0; i < MAX_NUM_TID; i++) {
 165                         if (node->is_11n_enabled)
 166                                 node->ampdu_sta[i] =
 167                                               priv->aggr_prio_tbl[i].ampdu_user;
 168                         else
 169                                 node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
 170                 }
 171                 memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
 172                 kfree(sinfo);
 173                 break;
 174         case EVENT_UAP_STA_DEAUTH:
 175                 deauth_mac = adapter->event_body +
 176                              MWIFIEX_UAP_EVENT_EXTRA_HEADER;
 177                 cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
 178 
 179                 if (priv->ap_11n_enabled) {
 180                         mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
 181                         mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
 182                 }
 183                 mwifiex_wmm_del_peer_ra_list(priv, deauth_mac);
 184                 mwifiex_del_sta_entry(priv, deauth_mac);
 185                 break;
 186         case EVENT_UAP_BSS_IDLE:
 187                 priv->media_connected = false;
 188                 priv->port_open = false;
 189                 mwifiex_clean_txrx(priv);
 190                 mwifiex_del_all_sta_list(priv);
 191                 break;
 192         case EVENT_UAP_BSS_ACTIVE:
 193                 priv->media_connected = true;
 194                 priv->port_open = true;
 195                 break;
 196         case EVENT_UAP_BSS_START:
 197                 mwifiex_dbg(adapter, EVENT,
 198                             "AP EVENT: event id: %#x\n", eventcause);
 199                 priv->port_open = false;
 200                 memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
 201                        ETH_ALEN);
 202                 if (priv->hist_data)
 203                         mwifiex_hist_data_reset(priv);
 204                 mwifiex_check_uap_capabilities(priv, adapter->event_skb);
 205                 break;
 206         case EVENT_UAP_MIC_COUNTERMEASURES:
 207                 /* For future development */
 208                 mwifiex_dbg(adapter, EVENT,
 209                             "AP EVENT: event id: %#x\n", eventcause);
 210                 break;
 211         case EVENT_AMSDU_AGGR_CTRL:
 212                 ctrl = get_unaligned_le16(adapter->event_body);
 213                 mwifiex_dbg(adapter, EVENT,
 214                             "event: AMSDU_AGGR_CTRL %d\n", ctrl);
 215 
 216                 if (priv->media_connected) {
 217                         adapter->tx_buf_size =
 218                                 min_t(u16, adapter->curr_tx_buf_size, ctrl);
 219                         mwifiex_dbg(adapter, EVENT,
 220                                     "event: tx_buf_size %d\n",
 221                                     adapter->tx_buf_size);
 222                 }
 223                 break;
 224         case EVENT_ADDBA:
 225                 mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
 226                 if (priv->media_connected)
 227                         mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
 228                                          HostCmd_ACT_GEN_SET, 0,
 229                                          adapter->event_body, false);
 230                 break;
 231         case EVENT_DELBA:
 232                 mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
 233                 if (priv->media_connected)
 234                         mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
 235                 break;
 236         case EVENT_BA_STREAM_TIEMOUT:
 237                 mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
 238                 if (priv->media_connected) {
 239                         ba_timeout = (void *)adapter->event_body;
 240                         mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
 241                 }
 242                 break;
 243         case EVENT_EXT_SCAN_REPORT:
 244                 mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
 245                 if (adapter->ext_scan)
 246                         return mwifiex_handle_event_ext_scan_report(priv,
 247                                                 adapter->event_skb->data);
 248                 break;
 249         case EVENT_TX_STATUS_REPORT:
 250                 mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
 251                 mwifiex_parse_tx_status_event(priv, adapter->event_body);
 252                 break;
 253         case EVENT_PS_SLEEP:
 254                 mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
 255 
 256                 adapter->ps_state = PS_STATE_PRE_SLEEP;
 257 
 258                 mwifiex_check_ps_cond(adapter);
 259                 break;
 260 
 261         case EVENT_PS_AWAKE:
 262                 mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
 263                 if (!adapter->pps_uapsd_mode &&
 264                     priv->media_connected && adapter->sleep_period.period) {
 265                                 adapter->pps_uapsd_mode = true;
 266                                 mwifiex_dbg(adapter, EVENT,
 267                                             "event: PPS/UAPSD mode activated\n");
 268                 }
 269                 adapter->tx_lock_flag = false;
 270                 if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
 271                         if (mwifiex_check_last_packet_indication(priv)) {
 272                                 if (adapter->data_sent ||
 273                                     (adapter->if_ops.is_port_ready &&
 274                                      !adapter->if_ops.is_port_ready(priv))) {
 275                                         adapter->ps_state = PS_STATE_AWAKE;
 276                                         adapter->pm_wakeup_card_req = false;
 277                                         adapter->pm_wakeup_fw_try = false;
 278                                         break;
 279                                 }
 280                                 if (!mwifiex_send_null_packet
 281                                         (priv,
 282                                          MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
 283                                          MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
 284                                                 adapter->ps_state =
 285                                                         PS_STATE_SLEEP;
 286                                         return 0;
 287                         }
 288                 }
 289                 adapter->ps_state = PS_STATE_AWAKE;
 290                 adapter->pm_wakeup_card_req = false;
 291                 adapter->pm_wakeup_fw_try = false;
 292                 break;
 293 
 294         case EVENT_CHANNEL_REPORT_RDY:
 295                 mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
 296                 mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
 297                 break;
 298         case EVENT_RADAR_DETECTED:
 299                 mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
 300                 mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
 301                 break;
 302         case EVENT_BT_COEX_WLAN_PARA_CHANGE:
 303                 mwifiex_dbg(adapter, EVENT, "event: BT coex wlan param update\n");
 304                 mwifiex_bt_coex_wlan_param_update_event(priv,
 305                                                         adapter->event_skb);
 306                 break;
 307         case EVENT_TX_DATA_PAUSE:
 308                 mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
 309                 mwifiex_process_tx_pause_event(priv, adapter->event_skb);
 310                 break;
 311 
 312         case EVENT_MULTI_CHAN_INFO:
 313                 mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
 314                 mwifiex_process_multi_chan_event(priv, adapter->event_skb);
 315                 break;
 316         case EVENT_RXBA_SYNC:
 317                 dev_dbg(adapter->dev, "EVENT: RXBA_SYNC\n");
 318                 mwifiex_11n_rxba_sync_event(priv, adapter->event_body,
 319                                             adapter->event_skb->len -
 320                                             sizeof(eventcause));
 321                 break;
 322 
 323         case EVENT_REMAIN_ON_CHAN_EXPIRED:
 324                 mwifiex_dbg(adapter, EVENT,
 325                             "event: uap: Remain on channel expired\n");
 326                 cfg80211_remain_on_channel_expired(&priv->wdev,
 327                                                    priv->roc_cfg.cookie,
 328                                                    &priv->roc_cfg.chan,
 329                                                    GFP_ATOMIC);
 330                 memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
 331                 break;
 332 
 333         default:
 334                 mwifiex_dbg(adapter, EVENT,
 335                             "event: unknown event id: %#x\n", eventcause);
 336                 break;
 337         }
 338 
 339         return 0;
 340 }
 341 
 342 /* This function deletes station entry from associated station list.
 343  * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream
 344  * tables created for this station are deleted.
 345  */
 346 void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
 347                               struct mwifiex_sta_node *node)
 348 {
 349         if (priv->ap_11n_enabled && node->is_11n_enabled) {
 350                 mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr);
 351                 mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr);
 352         }
 353         mwifiex_del_sta_entry(priv, node->mac_addr);
 354 
 355         return;
 356 }

/* [<][>][^][v][top][bottom][index][help] */