diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/uap_event.c')
| -rw-r--r-- | drivers/net/wireless/mwifiex/uap_event.c | 198 | 
1 files changed, 198 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c new file mode 100644 index 00000000000..92e77a398ec --- /dev/null +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -0,0 +1,198 @@ +/* + * Marvell Wireless LAN device driver: AP event handling + * + * Copyright (C) 2012, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License").  You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "main.h" +#include "11n.h" + + + + +/* + * This function handles AP interface specific events generated by firmware. + * + * Event specific routines are called by this function based + * upon the generated event cause. + * + * + * Events supported for AP - + *      - EVENT_UAP_STA_ASSOC + *      - EVENT_UAP_STA_DEAUTH + *      - EVENT_UAP_BSS_ACTIVE + *      - EVENT_UAP_BSS_START + *      - EVENT_UAP_BSS_IDLE + *      - EVENT_UAP_MIC_COUNTERMEASURES: + */ +int mwifiex_process_uap_event(struct mwifiex_private *priv) +{ +	struct mwifiex_adapter *adapter = priv->adapter; +	int len, i; +	u32 eventcause = adapter->event_cause; +	struct station_info sinfo; +	struct mwifiex_assoc_event *event; +	struct mwifiex_sta_node *node; +	u8 *deauth_mac; +	struct host_cmd_ds_11n_batimeout *ba_timeout; +	u16 ctrl; + +	switch (eventcause) { +	case EVENT_UAP_STA_ASSOC: +		memset(&sinfo, 0, sizeof(sinfo)); +		event = (struct mwifiex_assoc_event *) +			(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER); +		if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { +			len = -1; + +			if (ieee80211_is_assoc_req(event->frame_control)) +				len = 0; +			else if (ieee80211_is_reassoc_req(event->frame_control)) +				/* There will be ETH_ALEN bytes of +				 * current_ap_addr before the re-assoc ies. +				 */ +				len = ETH_ALEN; + +			if (len != -1) { +				sinfo.filled = STATION_INFO_ASSOC_REQ_IES; +				sinfo.assoc_req_ies = &event->data[len]; +				len = (u8 *)sinfo.assoc_req_ies - +				      (u8 *)&event->frame_control; +				sinfo.assoc_req_ies_len = +					le16_to_cpu(event->len) - (u16)len; +			} +		} +		cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, +				 GFP_KERNEL); + +		node = mwifiex_add_sta_entry(priv, event->sta_addr); +		if (!node) { +			dev_warn(adapter->dev, +				 "could not create station entry!\n"); +			return -1; +		} + +		if (!priv->ap_11n_enabled) +			break; + +		mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies, +				       sinfo.assoc_req_ies_len, node); + +		for (i = 0; i < MAX_NUM_TID; i++) { +			if (node->is_11n_enabled) +				node->ampdu_sta[i] = +					      priv->aggr_prio_tbl[i].ampdu_user; +			else +				node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; +		} +		memset(node->rx_seq, 0xff, sizeof(node->rx_seq)); +		break; +	case EVENT_UAP_STA_DEAUTH: +		deauth_mac = adapter->event_body + +			     MWIFIEX_UAP_EVENT_EXTRA_HEADER; +		cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL); + +		if (priv->ap_11n_enabled) { +			mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac); +			mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac); +		} +		mwifiex_del_sta_entry(priv, deauth_mac); +		break; +	case EVENT_UAP_BSS_IDLE: +		priv->media_connected = false; +		if (netif_carrier_ok(priv->netdev)) +			netif_carrier_off(priv->netdev); +		mwifiex_stop_net_dev_queue(priv->netdev, adapter); + +		mwifiex_clean_txrx(priv); +		mwifiex_del_all_sta_list(priv); +		break; +	case EVENT_UAP_BSS_ACTIVE: +		priv->media_connected = true; +		if (!netif_carrier_ok(priv->netdev)) +			netif_carrier_on(priv->netdev); +		mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); +		break; +	case EVENT_UAP_BSS_START: +		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); +		memcpy(priv->netdev->dev_addr, adapter->event_body + 2, +		       ETH_ALEN); +		break; +	case EVENT_UAP_MIC_COUNTERMEASURES: +		/* For future development */ +		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); +		break; +	case EVENT_AMSDU_AGGR_CTRL: +		ctrl = le16_to_cpu(*(__le16 *)adapter->event_body); +		dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl); + +		if (priv->media_connected) { +			adapter->tx_buf_size = +				min_t(u16, adapter->curr_tx_buf_size, ctrl); +			dev_dbg(adapter->dev, "event: tx_buf_size %d\n", +				adapter->tx_buf_size); +		} +		break; +	case EVENT_ADDBA: +		dev_dbg(adapter->dev, "event: ADDBA Request\n"); +		if (priv->media_connected) +			mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, +					 HostCmd_ACT_GEN_SET, 0, +					 adapter->event_body, false); +		break; +	case EVENT_DELBA: +		dev_dbg(adapter->dev, "event: DELBA Request\n"); +		if (priv->media_connected) +			mwifiex_11n_delete_ba_stream(priv, adapter->event_body); +		break; +	case EVENT_BA_STREAM_TIEMOUT: +		dev_dbg(adapter->dev, "event:  BA Stream timeout\n"); +		if (priv->media_connected) { +			ba_timeout = (void *)adapter->event_body; +			mwifiex_11n_ba_stream_timeout(priv, ba_timeout); +		} +		break; +	case EVENT_EXT_SCAN_REPORT: +		dev_dbg(adapter->dev, "event: EXT_SCAN Report\n"); +		if (adapter->ext_scan) +			return mwifiex_handle_event_ext_scan_report(priv, +						adapter->event_skb->data); +		break; +	default: +		dev_dbg(adapter->dev, "event: unknown event id: %#x\n", +			eventcause); +		break; +	} + +	return 0; +} + +/* This function deletes station entry from associated station list. + * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream + * tables created for this station are deleted. + */ +void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, +			      struct mwifiex_sta_node *node) +{ +	if (priv->ap_11n_enabled && node->is_11n_enabled) { +		mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr); +		mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr); +	} +	mwifiex_del_sta_entry(priv, node->mac_addr); + +	return; +}  | 
