cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

uap_event.c (10610B)


      1/*
      2 * NXP Wireless LAN device driver: AP event handling
      3 *
      4 * Copyright 2011-2020 NXP
      5 *
      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.
     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
     26static 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 */
    106int 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		eth_hw_addr_set(priv->netdev, adapter->event_body + 2);
    201		if (priv->hist_data)
    202			mwifiex_hist_data_reset(priv);
    203		mwifiex_check_uap_capabilities(priv, adapter->event_skb);
    204		break;
    205	case EVENT_UAP_MIC_COUNTERMEASURES:
    206		/* For future development */
    207		mwifiex_dbg(adapter, EVENT,
    208			    "AP EVENT: event id: %#x\n", eventcause);
    209		break;
    210	case EVENT_AMSDU_AGGR_CTRL:
    211		ctrl = get_unaligned_le16(adapter->event_body);
    212		mwifiex_dbg(adapter, EVENT,
    213			    "event: AMSDU_AGGR_CTRL %d\n", ctrl);
    214
    215		if (priv->media_connected) {
    216			adapter->tx_buf_size =
    217				min_t(u16, adapter->curr_tx_buf_size, ctrl);
    218			mwifiex_dbg(adapter, EVENT,
    219				    "event: tx_buf_size %d\n",
    220				    adapter->tx_buf_size);
    221		}
    222		break;
    223	case EVENT_ADDBA:
    224		mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
    225		if (priv->media_connected)
    226			mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
    227					 HostCmd_ACT_GEN_SET, 0,
    228					 adapter->event_body, false);
    229		break;
    230	case EVENT_DELBA:
    231		mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
    232		if (priv->media_connected)
    233			mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
    234		break;
    235	case EVENT_BA_STREAM_TIEMOUT:
    236		mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
    237		if (priv->media_connected) {
    238			ba_timeout = (void *)adapter->event_body;
    239			mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
    240		}
    241		break;
    242	case EVENT_EXT_SCAN_REPORT:
    243		mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
    244		if (adapter->ext_scan)
    245			return mwifiex_handle_event_ext_scan_report(priv,
    246						adapter->event_skb->data);
    247		break;
    248	case EVENT_TX_STATUS_REPORT:
    249		mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
    250		mwifiex_parse_tx_status_event(priv, adapter->event_body);
    251		break;
    252	case EVENT_PS_SLEEP:
    253		mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");
    254
    255		adapter->ps_state = PS_STATE_PRE_SLEEP;
    256
    257		mwifiex_check_ps_cond(adapter);
    258		break;
    259
    260	case EVENT_PS_AWAKE:
    261		mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
    262		if (!adapter->pps_uapsd_mode &&
    263		    priv->media_connected && adapter->sleep_period.period) {
    264				adapter->pps_uapsd_mode = true;
    265				mwifiex_dbg(adapter, EVENT,
    266					    "event: PPS/UAPSD mode activated\n");
    267		}
    268		adapter->tx_lock_flag = false;
    269		if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
    270			if (mwifiex_check_last_packet_indication(priv)) {
    271				if (adapter->data_sent ||
    272				    (adapter->if_ops.is_port_ready &&
    273				     !adapter->if_ops.is_port_ready(priv))) {
    274					adapter->ps_state = PS_STATE_AWAKE;
    275					adapter->pm_wakeup_card_req = false;
    276					adapter->pm_wakeup_fw_try = false;
    277					break;
    278				}
    279				if (!mwifiex_send_null_packet
    280					(priv,
    281					 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
    282					 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
    283						adapter->ps_state =
    284							PS_STATE_SLEEP;
    285					return 0;
    286			}
    287		}
    288		adapter->ps_state = PS_STATE_AWAKE;
    289		adapter->pm_wakeup_card_req = false;
    290		adapter->pm_wakeup_fw_try = false;
    291		break;
    292
    293	case EVENT_CHANNEL_REPORT_RDY:
    294		mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
    295		mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
    296		break;
    297	case EVENT_RADAR_DETECTED:
    298		mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
    299		mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
    300		break;
    301	case EVENT_BT_COEX_WLAN_PARA_CHANGE:
    302		mwifiex_dbg(adapter, EVENT, "event: BT coex wlan param update\n");
    303		mwifiex_bt_coex_wlan_param_update_event(priv,
    304							adapter->event_skb);
    305		break;
    306	case EVENT_TX_DATA_PAUSE:
    307		mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
    308		mwifiex_process_tx_pause_event(priv, adapter->event_skb);
    309		break;
    310
    311	case EVENT_MULTI_CHAN_INFO:
    312		mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
    313		mwifiex_process_multi_chan_event(priv, adapter->event_skb);
    314		break;
    315	case EVENT_RXBA_SYNC:
    316		dev_dbg(adapter->dev, "EVENT: RXBA_SYNC\n");
    317		mwifiex_11n_rxba_sync_event(priv, adapter->event_body,
    318					    adapter->event_skb->len -
    319					    sizeof(eventcause));
    320		break;
    321
    322	case EVENT_REMAIN_ON_CHAN_EXPIRED:
    323		mwifiex_dbg(adapter, EVENT,
    324			    "event: uap: Remain on channel expired\n");
    325		cfg80211_remain_on_channel_expired(&priv->wdev,
    326						   priv->roc_cfg.cookie,
    327						   &priv->roc_cfg.chan,
    328						   GFP_ATOMIC);
    329		memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
    330		break;
    331
    332	default:
    333		mwifiex_dbg(adapter, EVENT,
    334			    "event: unknown event id: %#x\n", eventcause);
    335		break;
    336	}
    337
    338	return 0;
    339}
    340
    341/* This function deletes station entry from associated station list.
    342 * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream
    343 * tables created for this station are deleted.
    344 */
    345void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
    346			      struct mwifiex_sta_node *node)
    347{
    348	if (priv->ap_11n_enabled && node->is_11n_enabled) {
    349		mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr);
    350		mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr);
    351	}
    352	mwifiex_del_sta_entry(priv, node->mac_addr);
    353
    354	return;
    355}