/*
 * Marvell Wireless LAN device driver: AP event handling
 *
 * Copyright (C) 2012-2014, 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.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_wmm_del_peer_ra_list(priv, deauth_mac);
		mwifiex_del_sta_entry(priv, deauth_mac);
		break;
	case EVENT_UAP_BSS_IDLE:
		priv->media_connected = false;
		mwifiex_clean_txrx(priv);
		mwifiex_del_all_sta_list(priv);
		break;
	case EVENT_UAP_BSS_ACTIVE:
		priv->media_connected = true;
		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);
		if (priv->hist_data)
			mwifiex_hist_data_reset(priv);
		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;
	case EVENT_TX_STATUS_REPORT:
		dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
		mwifiex_parse_tx_status_event(priv, adapter->event_body);
		break;
	case EVENT_PS_SLEEP:
		dev_dbg(adapter->dev, "info: EVENT: SLEEP\n");

		adapter->ps_state = PS_STATE_PRE_SLEEP;

		mwifiex_check_ps_cond(adapter);
		break;

	case EVENT_PS_AWAKE:
		dev_dbg(adapter->dev, "info: EVENT: AWAKE\n");
		if (!adapter->pps_uapsd_mode &&
		    priv->media_connected && adapter->sleep_period.period) {
				adapter->pps_uapsd_mode = true;
				dev_dbg(adapter->dev,
					"event: PPS/UAPSD mode activated\n");
		}
		adapter->tx_lock_flag = false;
		if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
			if (mwifiex_check_last_packet_indication(priv)) {
				if (adapter->data_sent) {
					adapter->ps_state = PS_STATE_AWAKE;
					adapter->pm_wakeup_card_req = false;
					adapter->pm_wakeup_fw_try = false;
					break;
				}
				if (!mwifiex_send_null_packet
					(priv,
					 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
					 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
						adapter->ps_state =
							PS_STATE_SLEEP;
					return 0;
			}
		}
		adapter->ps_state = PS_STATE_AWAKE;
		adapter->pm_wakeup_card_req = false;
		adapter->pm_wakeup_fw_try = false;
		break;

	case EVENT_CHANNEL_REPORT_RDY:
		dev_dbg(adapter->dev, "event: Channel Report\n");
		mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
		break;
	case EVENT_RADAR_DETECTED:
		dev_dbg(adapter->dev, "event: Radar detected\n");
		mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
		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;
}
