brintos

brintos / linux-shallow public Read only

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