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

join.c (49587B)


      1/*
      2 * NXP Wireless LAN device driver: association and ad-hoc start/join
      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 "ioctl.h"
     22#include "util.h"
     23#include "fw.h"
     24#include "main.h"
     25#include "wmm.h"
     26#include "11n.h"
     27#include "11ac.h"
     28
     29#define CAPINFO_MASK    (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9)))
     30
     31/*
     32 * Append a generic IE as a pass through TLV to a TLV buffer.
     33 *
     34 * This function is called from the network join command preparation routine.
     35 *
     36 * If the IE buffer has been setup by the application, this routine appends
     37 * the buffer as a pass through TLV type to the request.
     38 */
     39static int
     40mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer)
     41{
     42	int ret_len = 0;
     43	struct mwifiex_ie_types_header ie_header;
     44
     45	/* Null Checks */
     46	if (!buffer)
     47		return 0;
     48	if (!(*buffer))
     49		return 0;
     50
     51	/*
     52	 * If there is a generic ie buffer setup, append it to the return
     53	 *   parameter buffer pointer.
     54	 */
     55	if (priv->gen_ie_buf_len) {
     56		mwifiex_dbg(priv->adapter, INFO,
     57			    "info: %s: append generic ie len %d to %p\n",
     58			    __func__, priv->gen_ie_buf_len, *buffer);
     59
     60		/* Wrap the generic IE buffer with a pass through TLV type */
     61		ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
     62		ie_header.len = cpu_to_le16(priv->gen_ie_buf_len);
     63		memcpy(*buffer, &ie_header, sizeof(ie_header));
     64
     65		/* Increment the return size and the return buffer pointer
     66		   param */
     67		*buffer += sizeof(ie_header);
     68		ret_len += sizeof(ie_header);
     69
     70		/* Copy the generic IE buffer to the output buffer, advance
     71		   pointer */
     72		memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len);
     73
     74		/* Increment the return size and the return buffer pointer
     75		   param */
     76		*buffer += priv->gen_ie_buf_len;
     77		ret_len += priv->gen_ie_buf_len;
     78
     79		/* Reset the generic IE buffer */
     80		priv->gen_ie_buf_len = 0;
     81	}
     82
     83	/* return the length appended to the buffer */
     84	return ret_len;
     85}
     86
     87/*
     88 * Append TSF tracking info from the scan table for the target AP.
     89 *
     90 * This function is called from the network join command preparation routine.
     91 *
     92 * The TSF table TSF sent to the firmware contains two TSF values:
     93 *      - The TSF of the target AP from its previous beacon/probe response
     94 *      - The TSF timestamp of our local MAC at the time we observed the
     95 *        beacon/probe response.
     96 *
     97 * The firmware uses the timestamp values to set an initial TSF value
     98 * in the MAC for the new association after a reassociation attempt.
     99 */
    100static int
    101mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer,
    102			   struct mwifiex_bssdescriptor *bss_desc)
    103{
    104	struct mwifiex_ie_types_tsf_timestamp tsf_tlv;
    105	__le64 tsf_val;
    106
    107	/* Null Checks */
    108	if (buffer == NULL)
    109		return 0;
    110	if (*buffer == NULL)
    111		return 0;
    112
    113	memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp));
    114
    115	tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP);
    116	tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val));
    117
    118	memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header));
    119	*buffer += sizeof(tsf_tlv.header);
    120
    121	/* TSF at the time when beacon/probe_response was received */
    122	tsf_val = cpu_to_le64(bss_desc->fw_tsf);
    123	memcpy(*buffer, &tsf_val, sizeof(tsf_val));
    124	*buffer += sizeof(tsf_val);
    125
    126	tsf_val = cpu_to_le64(bss_desc->timestamp);
    127
    128	mwifiex_dbg(priv->adapter, INFO,
    129		    "info: %s: TSF offset calc: %016llx - %016llx\n",
    130		    __func__, bss_desc->timestamp, bss_desc->fw_tsf);
    131
    132	memcpy(*buffer, &tsf_val, sizeof(tsf_val));
    133	*buffer += sizeof(tsf_val);
    134
    135	return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val));
    136}
    137
    138/*
    139 * This function finds out the common rates between rate1 and rate2.
    140 *
    141 * It will fill common rates in rate1 as output if found.
    142 *
    143 * NOTE: Setting the MSB of the basic rates needs to be taken
    144 * care of, either before or after calling this function.
    145 */
    146static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
    147				    u32 rate1_size, u8 *rate2, u32 rate2_size)
    148{
    149	int ret;
    150	u8 *ptr = rate1, *tmp;
    151	u32 i, j;
    152
    153	tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
    154	if (!tmp) {
    155		mwifiex_dbg(priv->adapter, ERROR, "failed to alloc tmp buf\n");
    156		return -ENOMEM;
    157	}
    158
    159	memset(rate1, 0, rate1_size);
    160
    161	for (i = 0; i < rate2_size && rate2[i]; i++) {
    162		for (j = 0; j < rate1_size && tmp[j]; j++) {
    163			/* Check common rate, excluding the bit for
    164			   basic rate */
    165			if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) {
    166				*rate1++ = tmp[j];
    167				break;
    168			}
    169		}
    170	}
    171
    172	mwifiex_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n",
    173		    priv->data_rate);
    174
    175	if (!priv->is_data_rate_auto) {
    176		while (*ptr) {
    177			if ((*ptr & 0x7f) == priv->data_rate) {
    178				ret = 0;
    179				goto done;
    180			}
    181			ptr++;
    182		}
    183		mwifiex_dbg(priv->adapter, ERROR,
    184			    "previously set fixed data rate %#x\t"
    185			    "is not compatible with the network\n",
    186			    priv->data_rate);
    187
    188		ret = -1;
    189		goto done;
    190	}
    191
    192	ret = 0;
    193done:
    194	kfree(tmp);
    195	return ret;
    196}
    197
    198/*
    199 * This function creates the intersection of the rates supported by a
    200 * target BSS and our adapter settings for use in an assoc/join command.
    201 */
    202static int
    203mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
    204				 struct mwifiex_bssdescriptor *bss_desc,
    205				 u8 *out_rates, u32 *out_rates_size)
    206{
    207	u8 card_rates[MWIFIEX_SUPPORTED_RATES];
    208	u32 card_rates_size;
    209
    210	/* Copy AP supported rates */
    211	memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES);
    212	/* Get the STA supported rates */
    213	card_rates_size = mwifiex_get_active_data_rates(priv, card_rates);
    214	/* Get the common rates between AP and STA supported rates */
    215	if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES,
    216				     card_rates, card_rates_size)) {
    217		*out_rates_size = 0;
    218		mwifiex_dbg(priv->adapter, ERROR,
    219			    "%s: cannot get common rates\n",
    220			    __func__);
    221		return -1;
    222	}
    223
    224	*out_rates_size =
    225		min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES);
    226
    227	return 0;
    228}
    229
    230/*
    231 * This function appends a WPS IE. It is called from the network join command
    232 * preparation routine.
    233 *
    234 * If the IE buffer has been setup by the application, this routine appends
    235 * the buffer as a WPS TLV type to the request.
    236 */
    237static int
    238mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer)
    239{
    240	int retLen = 0;
    241	struct mwifiex_ie_types_header ie_header;
    242
    243	if (!buffer || !*buffer)
    244		return 0;
    245
    246	/*
    247	 * If there is a wps ie buffer setup, append it to the return
    248	 * parameter buffer pointer.
    249	 */
    250	if (priv->wps_ie_len) {
    251		mwifiex_dbg(priv->adapter, CMD,
    252			    "cmd: append wps ie %d to %p\n",
    253			    priv->wps_ie_len, *buffer);
    254
    255		/* Wrap the generic IE buffer with a pass through TLV type */
    256		ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH);
    257		ie_header.len = cpu_to_le16(priv->wps_ie_len);
    258		memcpy(*buffer, &ie_header, sizeof(ie_header));
    259		*buffer += sizeof(ie_header);
    260		retLen += sizeof(ie_header);
    261
    262		memcpy(*buffer, priv->wps_ie, priv->wps_ie_len);
    263		*buffer += priv->wps_ie_len;
    264		retLen += priv->wps_ie_len;
    265
    266	}
    267
    268	kfree(priv->wps_ie);
    269	priv->wps_ie_len = 0;
    270	return retLen;
    271}
    272
    273/*
    274 * This function appends a WAPI IE.
    275 *
    276 * This function is called from the network join command preparation routine.
    277 *
    278 * If the IE buffer has been setup by the application, this routine appends
    279 * the buffer as a WAPI TLV type to the request.
    280 */
    281static int
    282mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer)
    283{
    284	int retLen = 0;
    285	struct mwifiex_ie_types_header ie_header;
    286
    287	/* Null Checks */
    288	if (buffer == NULL)
    289		return 0;
    290	if (*buffer == NULL)
    291		return 0;
    292
    293	/*
    294	 * If there is a wapi ie buffer setup, append it to the return
    295	 *   parameter buffer pointer.
    296	 */
    297	if (priv->wapi_ie_len) {
    298		mwifiex_dbg(priv->adapter, CMD,
    299			    "cmd: append wapi ie %d to %p\n",
    300			    priv->wapi_ie_len, *buffer);
    301
    302		/* Wrap the generic IE buffer with a pass through TLV type */
    303		ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE);
    304		ie_header.len = cpu_to_le16(priv->wapi_ie_len);
    305		memcpy(*buffer, &ie_header, sizeof(ie_header));
    306
    307		/* Increment the return size and the return buffer pointer
    308		   param */
    309		*buffer += sizeof(ie_header);
    310		retLen += sizeof(ie_header);
    311
    312		/* Copy the wapi IE buffer to the output buffer, advance
    313		   pointer */
    314		memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len);
    315
    316		/* Increment the return size and the return buffer pointer
    317		   param */
    318		*buffer += priv->wapi_ie_len;
    319		retLen += priv->wapi_ie_len;
    320
    321	}
    322	/* return the length appended to the buffer */
    323	return retLen;
    324}
    325
    326/*
    327 * This function appends rsn ie tlv for wpa/wpa2 security modes.
    328 * It is called from the network join command preparation routine.
    329 */
    330static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
    331					  u8 **buffer)
    332{
    333	struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv;
    334	int rsn_ie_len;
    335
    336	if (!buffer || !(*buffer))
    337		return 0;
    338
    339	rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer);
    340	rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]);
    341	rsn_ie_tlv->header.type = cpu_to_le16(
    342				 le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF);
    343	rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]);
    344	rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len)
    345							 & 0x00FF);
    346	if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2))
    347		memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2],
    348		       le16_to_cpu(rsn_ie_tlv->header.len));
    349	else
    350		return -1;
    351
    352	rsn_ie_len = sizeof(rsn_ie_tlv->header) +
    353					le16_to_cpu(rsn_ie_tlv->header.len);
    354	*buffer += rsn_ie_len;
    355
    356	return rsn_ie_len;
    357}
    358
    359/*
    360 * This function prepares command for association.
    361 *
    362 * This sets the following parameters -
    363 *      - Peer MAC address
    364 *      - Listen interval
    365 *      - Beacon interval
    366 *      - Capability information
    367 *
    368 * ...and the following TLVs, as required -
    369 *      - SSID TLV
    370 *      - PHY TLV
    371 *      - SS TLV
    372 *      - Rates TLV
    373 *      - Authentication TLV
    374 *      - Channel TLV
    375 *      - WPA/WPA2 IE
    376 *      - 11n TLV
    377 *      - Vendor specific TLV
    378 *      - WMM TLV
    379 *      - WAPI IE
    380 *      - Generic IE
    381 *      - TSF TLV
    382 *
    383 * Preparation also includes -
    384 *      - Setting command ID and proper size
    385 *      - Ensuring correct endian-ness
    386 */
    387int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
    388				 struct host_cmd_ds_command *cmd,
    389				 struct mwifiex_bssdescriptor *bss_desc)
    390{
    391	struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
    392	struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
    393	struct mwifiex_ie_types_phy_param_set *phy_tlv;
    394	struct mwifiex_ie_types_ss_param_set *ss_tlv;
    395	struct mwifiex_ie_types_rates_param_set *rates_tlv;
    396	struct mwifiex_ie_types_auth_type *auth_tlv;
    397	struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
    398	u8 rates[MWIFIEX_SUPPORTED_RATES];
    399	u32 rates_size;
    400	u16 tmp_cap;
    401	u8 *pos;
    402	int rsn_ie_len = 0;
    403
    404	pos = (u8 *) assoc;
    405
    406	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
    407
    408	/* Save so we know which BSS Desc to use in the response handler */
    409	priv->attempted_bss_desc = bss_desc;
    410
    411	memcpy(assoc->peer_sta_addr,
    412	       bss_desc->mac_address, sizeof(assoc->peer_sta_addr));
    413	pos += sizeof(assoc->peer_sta_addr);
    414
    415	/* Set the listen interval */
    416	assoc->listen_interval = cpu_to_le16(priv->listen_interval);
    417	/* Set the beacon period */
    418	assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period);
    419
    420	pos += sizeof(assoc->cap_info_bitmap);
    421	pos += sizeof(assoc->listen_interval);
    422	pos += sizeof(assoc->beacon_period);
    423	pos += sizeof(assoc->dtim_period);
    424
    425	ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos;
    426	ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID);
    427	ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len);
    428	memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid,
    429	       le16_to_cpu(ssid_tlv->header.len));
    430	pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len);
    431
    432	phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos;
    433	phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS);
    434	phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set));
    435	memcpy(&phy_tlv->fh_ds.ds_param_set,
    436	       &bss_desc->phy_param_set.ds_param_set.current_chan,
    437	       sizeof(phy_tlv->fh_ds.ds_param_set));
    438	pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len);
    439
    440	ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos;
    441	ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS);
    442	ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set));
    443	pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len);
    444
    445	/* Get the common rates supported between the driver and the BSS Desc */
    446	if (mwifiex_setup_rates_from_bssdesc
    447	    (priv, bss_desc, rates, &rates_size))
    448		return -1;
    449
    450	/* Save the data rates into Current BSS state structure */
    451	priv->curr_bss_params.num_of_rates = rates_size;
    452	memcpy(&priv->curr_bss_params.data_rates, rates, rates_size);
    453
    454	/* Setup the Rates TLV in the association command */
    455	rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos;
    456	rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
    457	rates_tlv->header.len = cpu_to_le16((u16) rates_size);
    458	memcpy(rates_tlv->rates, rates, rates_size);
    459	pos += sizeof(rates_tlv->header) + rates_size;
    460	mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n",
    461		    rates_size);
    462
    463	/* Add the Authentication type to be used for Auth frames */
    464	auth_tlv = (struct mwifiex_ie_types_auth_type *) pos;
    465	auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
    466	auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type));
    467	if (priv->sec_info.wep_enabled)
    468		auth_tlv->auth_type = cpu_to_le16(
    469				(u16) priv->sec_info.authentication_mode);
    470	else
    471		auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM);
    472
    473	pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len);
    474
    475	if (IS_SUPPORT_MULTI_BANDS(priv->adapter) &&
    476	    !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
    477	    (!bss_desc->disable_11n) &&
    478	    (priv->adapter->config_bands & BAND_GN ||
    479	     priv->adapter->config_bands & BAND_AN) &&
    480	    (bss_desc->bcn_ht_cap)
    481	    )
    482		) {
    483		/* Append a channel TLV for the channel the attempted AP was
    484		   found on */
    485		chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
    486		chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
    487		chan_tlv->header.len =
    488			cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
    489
    490		memset(chan_tlv->chan_scan_param, 0x00,
    491		       sizeof(struct mwifiex_chan_scan_param_set));
    492		chan_tlv->chan_scan_param[0].chan_number =
    493			(bss_desc->phy_param_set.ds_param_set.current_chan);
    494		mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan = %d\n",
    495			    chan_tlv->chan_scan_param[0].chan_number);
    496
    497		chan_tlv->chan_scan_param[0].radio_type =
    498			mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
    499
    500		mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Band = %d\n",
    501			    chan_tlv->chan_scan_param[0].radio_type);
    502		pos += sizeof(chan_tlv->header) +
    503			sizeof(struct mwifiex_chan_scan_param_set);
    504	}
    505
    506	if (!priv->wps.session_enable) {
    507		if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
    508			rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
    509
    510		if (rsn_ie_len == -1)
    511			return -1;
    512	}
    513
    514	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
    515	    (!bss_desc->disable_11n) &&
    516	    (priv->adapter->config_bands & BAND_GN ||
    517	     priv->adapter->config_bands & BAND_AN))
    518		mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos);
    519
    520	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
    521	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
    522	    priv->adapter->config_bands & BAND_AAC)
    523		mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos);
    524
    525	/* Append vendor specific IE TLV */
    526	mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos);
    527
    528	mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie,
    529					    bss_desc->bcn_ht_cap);
    530	if (priv->sec_info.wapi_enabled && priv->wapi_ie_len)
    531		mwifiex_cmd_append_wapi_ie(priv, &pos);
    532
    533	if (priv->wps.session_enable && priv->wps_ie_len)
    534		mwifiex_cmd_append_wps_ie(priv, &pos);
    535
    536	mwifiex_cmd_append_generic_ie(priv, &pos);
    537
    538	mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc);
    539
    540	mwifiex_11h_process_join(priv, &pos, bss_desc);
    541
    542	cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN);
    543
    544	/* Set the Capability info at last */
    545	tmp_cap = bss_desc->cap_info_bitmap;
    546
    547	if (priv->adapter->config_bands == BAND_B)
    548		tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
    549
    550	tmp_cap &= CAPINFO_MASK;
    551	mwifiex_dbg(priv->adapter, INFO,
    552		    "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
    553		    tmp_cap, CAPINFO_MASK);
    554	assoc->cap_info_bitmap = cpu_to_le16(tmp_cap);
    555
    556	return 0;
    557}
    558
    559static const char *assoc_failure_reason_to_str(u16 cap_info)
    560{
    561	switch (cap_info) {
    562	case CONNECT_ERR_AUTH_ERR_STA_FAILURE:
    563		return "CONNECT_ERR_AUTH_ERR_STA_FAILURE";
    564	case CONNECT_ERR_AUTH_MSG_UNHANDLED:
    565		return "CONNECT_ERR_AUTH_MSG_UNHANDLED";
    566	case CONNECT_ERR_ASSOC_ERR_TIMEOUT:
    567		return "CONNECT_ERR_ASSOC_ERR_TIMEOUT";
    568	case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED:
    569		return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED";
    570	case CONNECT_ERR_STA_FAILURE:
    571		return "CONNECT_ERR_STA_FAILURE";
    572	}
    573
    574	return "Unknown connect failure";
    575}
    576/*
    577 * Association firmware command response handler
    578 *
    579 * The response buffer for the association command has the following
    580 * memory layout.
    581 *
    582 * For cases where an association response was not received (indicated
    583 * by the CapInfo and AId field):
    584 *
    585 *     .------------------------------------------------------------.
    586 *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
    587 *     .------------------------------------------------------------.
    588 *     |  cap_info/Error Return(t_u16):                             |
    589 *     |           0xFFFF(-1): Internal error                       |
    590 *     |           0xFFFE(-2): Authentication unhandled message     |
    591 *     |           0xFFFD(-3): Authentication refused               |
    592 *     |           0xFFFC(-4): Timeout waiting for AP response      |
    593 *     .------------------------------------------------------------.
    594 *     |  status_code(t_u16):                                       |
    595 *     |        If cap_info is -1:                                  |
    596 *     |           An internal firmware failure prevented the       |
    597 *     |           command from being processed.  The status_code   |
    598 *     |           will be set to 1.                                |
    599 *     |                                                            |
    600 *     |        If cap_info is -2:                                  |
    601 *     |           An authentication frame was received but was     |
    602 *     |           not handled by the firmware.  IEEE Status        |
    603 *     |           code for the failure is returned.                |
    604 *     |                                                            |
    605 *     |        If cap_info is -3:                                  |
    606 *     |           An authentication frame was received and the     |
    607 *     |           status_code is the IEEE Status reported in the   |
    608 *     |           response.                                        |
    609 *     |                                                            |
    610 *     |        If cap_info is -4:                                  |
    611 *     |           (1) Association response timeout                 |
    612 *     |           (2) Authentication response timeout              |
    613 *     .------------------------------------------------------------.
    614 *     |  a_id(t_u16): 0xFFFF                                       |
    615 *     .------------------------------------------------------------.
    616 *
    617 *
    618 * For cases where an association response was received, the IEEE
    619 * standard association response frame is returned:
    620 *
    621 *     .------------------------------------------------------------.
    622 *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
    623 *     .------------------------------------------------------------.
    624 *     |  cap_info(t_u16): IEEE Capability                          |
    625 *     .------------------------------------------------------------.
    626 *     |  status_code(t_u16): IEEE Status Code                      |
    627 *     .------------------------------------------------------------.
    628 *     |  a_id(t_u16): IEEE Association ID                          |
    629 *     .------------------------------------------------------------.
    630 *     |  IEEE IEs(variable): Any received IEs comprising the       |
    631 *     |                      remaining portion of a received       |
    632 *     |                      association response frame.           |
    633 *     .------------------------------------------------------------.
    634 *
    635 * For simplistic handling, the status_code field can be used to determine
    636 * an association success (0) or failure (non-zero).
    637 */
    638int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
    639			     struct host_cmd_ds_command *resp)
    640{
    641	struct mwifiex_adapter *adapter = priv->adapter;
    642	int ret = 0;
    643	struct ieee_types_assoc_rsp *assoc_rsp;
    644	struct mwifiex_bssdescriptor *bss_desc;
    645	bool enable_data = true;
    646	u16 cap_info, status_code, aid;
    647	const u8 *ie_ptr;
    648	struct ieee80211_ht_operation *assoc_resp_ht_oper;
    649
    650	if (!priv->attempted_bss_desc) {
    651		mwifiex_dbg(priv->adapter, ERROR,
    652			    "ASSOC_RESP: failed, association terminated by host\n");
    653		goto done;
    654	}
    655
    656	assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;
    657
    658	cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap);
    659	status_code = le16_to_cpu(assoc_rsp->status_code);
    660	aid = le16_to_cpu(assoc_rsp->a_id);
    661
    662	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
    663		dev_err(priv->adapter->dev,
    664			"invalid AID value 0x%x; bits 15:14 not set\n",
    665			aid);
    666
    667	aid &= ~(BIT(15) | BIT(14));
    668
    669	priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
    670				   sizeof(priv->assoc_rsp_buf));
    671
    672	assoc_rsp->a_id = cpu_to_le16(aid);
    673	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);
    674
    675	if (status_code) {
    676		priv->adapter->dbg.num_cmd_assoc_failure++;
    677		mwifiex_dbg(priv->adapter, ERROR,
    678			    "ASSOC_RESP: failed,\t"
    679			    "status code=%d err=%#x a_id=%#x\n",
    680			    status_code, cap_info,
    681			    le16_to_cpu(assoc_rsp->a_id));
    682
    683		mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n",
    684			    assoc_failure_reason_to_str(cap_info));
    685		if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) {
    686			if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) {
    687				ret = WLAN_STATUS_AUTH_TIMEOUT;
    688				mwifiex_dbg(priv->adapter, ERROR,
    689					    "ASSOC_RESP: AUTH timeout\n");
    690			} else {
    691				ret = WLAN_STATUS_UNSPECIFIED_FAILURE;
    692				mwifiex_dbg(priv->adapter, ERROR,
    693					    "ASSOC_RESP: UNSPECIFIED failure\n");
    694			}
    695		} else {
    696			ret = status_code;
    697		}
    698
    699		goto done;
    700	}
    701
    702	/* Send a Media Connected event, according to the Spec */
    703	priv->media_connected = true;
    704
    705	priv->adapter->ps_state = PS_STATE_AWAKE;
    706	priv->adapter->pps_uapsd_mode = false;
    707	priv->adapter->tx_lock_flag = false;
    708
    709	/* Set the attempted BSSID Index to current */
    710	bss_desc = priv->attempted_bss_desc;
    711
    712	mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n",
    713		    bss_desc->ssid.ssid);
    714
    715	/* Make a copy of current BSSID descriptor */
    716	memcpy(&priv->curr_bss_params.bss_descriptor,
    717	       bss_desc, sizeof(struct mwifiex_bssdescriptor));
    718
    719	/* Update curr_bss_params */
    720	priv->curr_bss_params.bss_descriptor.channel
    721		= bss_desc->phy_param_set.ds_param_set.current_chan;
    722
    723	priv->curr_bss_params.band = (u8) bss_desc->bss_band;
    724
    725	if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
    726		priv->curr_bss_params.wmm_enabled = true;
    727	else
    728		priv->curr_bss_params.wmm_enabled = false;
    729
    730	if ((priv->wmm_required || bss_desc->bcn_ht_cap) &&
    731	    priv->curr_bss_params.wmm_enabled)
    732		priv->wmm_enabled = true;
    733	else
    734		priv->wmm_enabled = false;
    735
    736	priv->curr_bss_params.wmm_uapsd_enabled = false;
    737
    738	if (priv->wmm_enabled)
    739		priv->curr_bss_params.wmm_uapsd_enabled
    740			= ((bss_desc->wmm_ie.qos_info_bitmap &
    741				IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0);
    742
    743	/* Store the bandwidth information from assoc response */
    744	ie_ptr = cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer,
    745				  priv->assoc_rsp_size
    746				  - sizeof(struct ieee_types_assoc_rsp));
    747	if (ie_ptr) {
    748		assoc_resp_ht_oper = (struct ieee80211_ht_operation *)(ie_ptr
    749					+ sizeof(struct ieee_types_header));
    750		priv->assoc_resp_ht_param = assoc_resp_ht_oper->ht_param;
    751		priv->ht_param_present = true;
    752	} else {
    753		priv->ht_param_present = false;
    754	}
    755
    756	mwifiex_dbg(priv->adapter, INFO,
    757		    "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
    758		    priv->curr_pkt_filter);
    759	if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
    760		priv->wpa_is_gtk_set = false;
    761
    762	if (priv->wmm_enabled) {
    763		/* Don't re-enable carrier until we get the WMM_GET_STATUS
    764		   event */
    765		enable_data = false;
    766	} else {
    767		/* Since WMM is not enabled, setup the queues with the
    768		   defaults */
    769		mwifiex_wmm_setup_queue_priorities(priv, NULL);
    770		mwifiex_wmm_setup_ac_downgrade(priv);
    771	}
    772
    773	if (enable_data)
    774		mwifiex_dbg(priv->adapter, INFO,
    775			    "info: post association, re-enabling data flow\n");
    776
    777	/* Reset SNR/NF/RSSI values */
    778	priv->data_rssi_last = 0;
    779	priv->data_nf_last = 0;
    780	priv->data_rssi_avg = 0;
    781	priv->data_nf_avg = 0;
    782	priv->bcn_rssi_last = 0;
    783	priv->bcn_nf_last = 0;
    784	priv->bcn_rssi_avg = 0;
    785	priv->bcn_nf_avg = 0;
    786	priv->rxpd_rate = 0;
    787	priv->rxpd_htinfo = 0;
    788
    789	mwifiex_save_curr_bcn(priv);
    790
    791	priv->adapter->dbg.num_cmd_assoc_success++;
    792
    793	mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n");
    794
    795	/* Add the ra_list here for infra mode as there will be only 1 ra
    796	   always */
    797	mwifiex_ralist_add(priv,
    798			   priv->curr_bss_params.bss_descriptor.mac_address);
    799
    800	if (!netif_carrier_ok(priv->netdev))
    801		netif_carrier_on(priv->netdev);
    802	mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
    803
    804	if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
    805		priv->scan_block = true;
    806	else
    807		priv->port_open = true;
    808
    809done:
    810	/* Need to indicate IOCTL complete */
    811	if (adapter->curr_cmd->wait_q_enabled) {
    812		if (ret)
    813			adapter->cmd_wait_q.status = -1;
    814		else
    815			adapter->cmd_wait_q.status = 0;
    816	}
    817
    818	return ret;
    819}
    820
    821/*
    822 * This function prepares command for ad-hoc start.
    823 *
    824 * Driver will fill up SSID, BSS mode, IBSS parameters, physical
    825 * parameters, probe delay, and capability information. Firmware
    826 * will fill up beacon period, basic rates and operational rates.
    827 *
    828 * In addition, the following TLVs are added -
    829 *      - Channel TLV
    830 *      - Vendor specific IE
    831 *      - WPA/WPA2 IE
    832 *      - HT Capabilities IE
    833 *      - HT Information IE
    834 *
    835 * Preparation also includes -
    836 *      - Setting command ID and proper size
    837 *      - Ensuring correct endian-ness
    838 */
    839int
    840mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
    841				struct host_cmd_ds_command *cmd,
    842				struct cfg80211_ssid *req_ssid)
    843{
    844	int rsn_ie_len = 0;
    845	struct mwifiex_adapter *adapter = priv->adapter;
    846	struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start =
    847		&cmd->params.adhoc_start;
    848	struct mwifiex_bssdescriptor *bss_desc;
    849	u32 cmd_append_size = 0;
    850	u32 i;
    851	u16 tmp_cap;
    852	struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
    853	u8 radio_type;
    854
    855	struct mwifiex_ie_types_htcap *ht_cap;
    856	struct mwifiex_ie_types_htinfo *ht_info;
    857	u8 *pos = (u8 *) adhoc_start +
    858			sizeof(struct host_cmd_ds_802_11_ad_hoc_start);
    859
    860	if (!adapter)
    861		return -1;
    862
    863	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
    864
    865	bss_desc = &priv->curr_bss_params.bss_descriptor;
    866	priv->attempted_bss_desc = bss_desc;
    867
    868	/*
    869	 * Fill in the parameters for 2 data structures:
    870	 *   1. struct host_cmd_ds_802_11_ad_hoc_start command
    871	 *   2. bss_desc
    872	 * Driver will fill up SSID, bss_mode,IBSS param, Physical Param,
    873	 * probe delay, and Cap info.
    874	 * Firmware will fill up beacon period, Basic rates
    875	 * and operational rates.
    876	 */
    877
    878	memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
    879
    880	if (req_ssid->ssid_len > IEEE80211_MAX_SSID_LEN)
    881		req_ssid->ssid_len = IEEE80211_MAX_SSID_LEN;
    882	memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
    883
    884	mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n",
    885		    adhoc_start->ssid);
    886
    887	memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
    888	memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
    889
    890	bss_desc->ssid.ssid_len = req_ssid->ssid_len;
    891
    892	/* Set the BSS mode */
    893	adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
    894	bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
    895	adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period);
    896	bss_desc->beacon_period = priv->beacon_period;
    897
    898	/* Set Physical param set */
    899/* Parameter IE Id */
    900#define DS_PARA_IE_ID   3
    901/* Parameter IE length */
    902#define DS_PARA_IE_LEN  1
    903
    904	adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID;
    905	adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN;
    906
    907	if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band,
    908			     (u16) priv->adhoc_channel, 0)) {
    909		struct mwifiex_chan_freq_power *cfp;
    910		cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band,
    911				      FIRST_VALID_CHANNEL, 0);
    912		if (cfp)
    913			priv->adhoc_channel = (u8) cfp->channel;
    914	}
    915
    916	if (!priv->adhoc_channel) {
    917		mwifiex_dbg(adapter, ERROR,
    918			    "ADHOC_S_CMD: adhoc_channel cannot be 0\n");
    919		return -1;
    920	}
    921
    922	mwifiex_dbg(adapter, INFO,
    923		    "info: ADHOC_S_CMD: creating ADHOC on channel %d\n",
    924		    priv->adhoc_channel);
    925
    926	priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel;
    927	priv->curr_bss_params.band = adapter->adhoc_start_band;
    928
    929	bss_desc->channel = priv->adhoc_channel;
    930	adhoc_start->phy_param_set.ds_param_set.current_chan =
    931		priv->adhoc_channel;
    932
    933	memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set,
    934	       sizeof(union ieee_types_phy_param_set));
    935
    936	/* Set IBSS param set */
    937/* IBSS parameter IE Id */
    938#define IBSS_PARA_IE_ID   6
    939/* IBSS parameter IE length */
    940#define IBSS_PARA_IE_LEN  2
    941
    942	adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID;
    943	adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN;
    944	adhoc_start->ss_param_set.ibss_param_set.atim_window
    945					= cpu_to_le16(priv->atim_window);
    946	memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set,
    947	       sizeof(union ieee_types_ss_param_set));
    948
    949	/* Set Capability info */
    950	bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS;
    951	tmp_cap = WLAN_CAPABILITY_IBSS;
    952
    953	/* Set up privacy in bss_desc */
    954	if (priv->sec_info.encryption_mode) {
    955		/* Ad-Hoc capability privacy on */
    956		mwifiex_dbg(adapter, INFO,
    957			    "info: ADHOC_S_CMD: wep_status set privacy to WEP\n");
    958		bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
    959		tmp_cap |= WLAN_CAPABILITY_PRIVACY;
    960	} else {
    961		mwifiex_dbg(adapter, INFO,
    962			    "info: ADHOC_S_CMD: wep_status NOT set,\t"
    963			    "setting privacy to ACCEPT ALL\n");
    964		bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
    965	}
    966
    967	memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate));
    968	mwifiex_get_active_data_rates(priv, adhoc_start->data_rate);
    969	if ((adapter->adhoc_start_band & BAND_G) &&
    970	    (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
    971		if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
    972				     HostCmd_ACT_GEN_SET, 0,
    973				     &priv->curr_pkt_filter, false)) {
    974			mwifiex_dbg(adapter, ERROR,
    975				    "ADHOC_S_CMD: G Protection config failed\n");
    976			return -1;
    977		}
    978	}
    979	/* Find the last non zero */
    980	for (i = 0; i < sizeof(adhoc_start->data_rate); i++)
    981		if (!adhoc_start->data_rate[i])
    982			break;
    983
    984	priv->curr_bss_params.num_of_rates = i;
    985
    986	/* Copy the ad-hoc creating rates into Current BSS rate structure */
    987	memcpy(&priv->curr_bss_params.data_rates,
    988	       &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates);
    989
    990	mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: rates=%4ph\n",
    991		    adhoc_start->data_rate);
    992
    993	mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n");
    994
    995	if (IS_SUPPORT_MULTI_BANDS(adapter)) {
    996		/* Append a channel TLV */
    997		chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
    998		chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
    999		chan_tlv->header.len =
   1000			cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
   1001
   1002		memset(chan_tlv->chan_scan_param, 0x00,
   1003		       sizeof(struct mwifiex_chan_scan_param_set));
   1004		chan_tlv->chan_scan_param[0].chan_number =
   1005			(u8) priv->curr_bss_params.bss_descriptor.channel;
   1006
   1007		mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Chan = %d\n",
   1008			    chan_tlv->chan_scan_param[0].chan_number);
   1009
   1010		chan_tlv->chan_scan_param[0].radio_type
   1011		       = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
   1012		if (adapter->adhoc_start_band & BAND_GN ||
   1013		    adapter->adhoc_start_band & BAND_AN) {
   1014			if (adapter->sec_chan_offset ==
   1015					    IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
   1016				chan_tlv->chan_scan_param[0].radio_type |=
   1017					(IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
   1018			else if (adapter->sec_chan_offset ==
   1019					    IEEE80211_HT_PARAM_CHA_SEC_BELOW)
   1020				chan_tlv->chan_scan_param[0].radio_type |=
   1021					(IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
   1022		}
   1023		mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Band = %d\n",
   1024			    chan_tlv->chan_scan_param[0].radio_type);
   1025		pos += sizeof(chan_tlv->header) +
   1026			sizeof(struct mwifiex_chan_scan_param_set);
   1027		cmd_append_size +=
   1028			sizeof(chan_tlv->header) +
   1029			sizeof(struct mwifiex_chan_scan_param_set);
   1030	}
   1031
   1032	/* Append vendor specific IE TLV */
   1033	cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
   1034				MWIFIEX_VSIE_MASK_ADHOC, &pos);
   1035
   1036	if (priv->sec_info.wpa_enabled) {
   1037		rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
   1038		if (rsn_ie_len == -1)
   1039			return -1;
   1040		cmd_append_size += rsn_ie_len;
   1041	}
   1042
   1043	if (adapter->adhoc_11n_enabled) {
   1044		/* Fill HT CAPABILITY */
   1045		ht_cap = (struct mwifiex_ie_types_htcap *) pos;
   1046		memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
   1047		ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
   1048		ht_cap->header.len =
   1049		       cpu_to_le16(sizeof(struct ieee80211_ht_cap));
   1050		radio_type = mwifiex_band_to_radio_type(
   1051					priv->adapter->config_bands);
   1052		mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
   1053
   1054		if (adapter->sec_chan_offset ==
   1055					IEEE80211_HT_PARAM_CHA_SEC_NONE) {
   1056			u16 tmp_ht_cap;
   1057
   1058			tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info);
   1059			tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
   1060			tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40;
   1061			ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap);
   1062		}
   1063
   1064		pos += sizeof(struct mwifiex_ie_types_htcap);
   1065		cmd_append_size += sizeof(struct mwifiex_ie_types_htcap);
   1066
   1067		/* Fill HT INFORMATION */
   1068		ht_info = (struct mwifiex_ie_types_htinfo *) pos;
   1069		memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo));
   1070		ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION);
   1071		ht_info->header.len =
   1072			cpu_to_le16(sizeof(struct ieee80211_ht_operation));
   1073
   1074		ht_info->ht_oper.primary_chan =
   1075			(u8) priv->curr_bss_params.bss_descriptor.channel;
   1076		if (adapter->sec_chan_offset) {
   1077			ht_info->ht_oper.ht_param = adapter->sec_chan_offset;
   1078			ht_info->ht_oper.ht_param |=
   1079					IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
   1080		}
   1081		ht_info->ht_oper.operation_mode =
   1082		     cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
   1083		ht_info->ht_oper.basic_set[0] = 0xff;
   1084		pos += sizeof(struct mwifiex_ie_types_htinfo);
   1085		cmd_append_size +=
   1086				sizeof(struct mwifiex_ie_types_htinfo);
   1087	}
   1088
   1089	cmd->size =
   1090		cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start)
   1091				  + S_DS_GEN + cmd_append_size));
   1092
   1093	if (adapter->adhoc_start_band == BAND_B)
   1094		tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
   1095	else
   1096		tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
   1097
   1098	adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap);
   1099
   1100	return 0;
   1101}
   1102
   1103/*
   1104 * This function prepares command for ad-hoc join.
   1105 *
   1106 * Most of the parameters are set up by copying from the target BSS descriptor
   1107 * from the scan response.
   1108 *
   1109 * In addition, the following TLVs are added -
   1110 *      - Channel TLV
   1111 *      - Vendor specific IE
   1112 *      - WPA/WPA2 IE
   1113 *      - 11n IE
   1114 *
   1115 * Preparation also includes -
   1116 *      - Setting command ID and proper size
   1117 *      - Ensuring correct endian-ness
   1118 */
   1119int
   1120mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
   1121			       struct host_cmd_ds_command *cmd,
   1122			       struct mwifiex_bssdescriptor *bss_desc)
   1123{
   1124	int rsn_ie_len = 0;
   1125	struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
   1126		&cmd->params.adhoc_join;
   1127	struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
   1128	u32 cmd_append_size = 0;
   1129	u16 tmp_cap;
   1130	u32 i, rates_size = 0;
   1131	u16 curr_pkt_filter;
   1132	u8 *pos =
   1133		(u8 *) adhoc_join +
   1134		sizeof(struct host_cmd_ds_802_11_ad_hoc_join);
   1135
   1136/* Use G protection */
   1137#define USE_G_PROTECTION        0x02
   1138	if (bss_desc->erp_flags & USE_G_PROTECTION) {
   1139		curr_pkt_filter =
   1140			priv->
   1141			curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
   1142
   1143		if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
   1144				     HostCmd_ACT_GEN_SET, 0,
   1145				     &curr_pkt_filter, false)) {
   1146			mwifiex_dbg(priv->adapter, ERROR,
   1147				    "ADHOC_J_CMD: G Protection config failed\n");
   1148			return -1;
   1149		}
   1150	}
   1151
   1152	priv->attempted_bss_desc = bss_desc;
   1153
   1154	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
   1155
   1156	adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS;
   1157
   1158	adhoc_join->bss_descriptor.beacon_period
   1159		= cpu_to_le16(bss_desc->beacon_period);
   1160
   1161	memcpy(&adhoc_join->bss_descriptor.bssid,
   1162	       &bss_desc->mac_address, ETH_ALEN);
   1163
   1164	memcpy(&adhoc_join->bss_descriptor.ssid,
   1165	       &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len);
   1166
   1167	memcpy(&adhoc_join->bss_descriptor.phy_param_set,
   1168	       &bss_desc->phy_param_set,
   1169	       sizeof(union ieee_types_phy_param_set));
   1170
   1171	memcpy(&adhoc_join->bss_descriptor.ss_param_set,
   1172	       &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set));
   1173
   1174	tmp_cap = bss_desc->cap_info_bitmap;
   1175
   1176	tmp_cap &= CAPINFO_MASK;
   1177
   1178	mwifiex_dbg(priv->adapter, INFO,
   1179		    "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n",
   1180		    tmp_cap, CAPINFO_MASK);
   1181
   1182	/* Information on BSSID descriptor passed to FW */
   1183	mwifiex_dbg(priv->adapter, INFO,
   1184		    "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n",
   1185		    adhoc_join->bss_descriptor.bssid,
   1186		    adhoc_join->bss_descriptor.ssid);
   1187
   1188	for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
   1189		    bss_desc->supported_rates[i]; i++)
   1190		;
   1191	rates_size = i;
   1192
   1193	/* Copy Data Rates from the Rates recorded in scan response */
   1194	memset(adhoc_join->bss_descriptor.data_rates, 0,
   1195	       sizeof(adhoc_join->bss_descriptor.data_rates));
   1196	memcpy(adhoc_join->bss_descriptor.data_rates,
   1197	       bss_desc->supported_rates, rates_size);
   1198
   1199	/* Copy the adhoc join rates into Current BSS state structure */
   1200	priv->curr_bss_params.num_of_rates = rates_size;
   1201	memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates,
   1202	       rates_size);
   1203
   1204	/* Copy the channel information */
   1205	priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel;
   1206	priv->curr_bss_params.band = (u8) bss_desc->bss_band;
   1207
   1208	if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled)
   1209		tmp_cap |= WLAN_CAPABILITY_PRIVACY;
   1210
   1211	if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) {
   1212		/* Append a channel TLV */
   1213		chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos;
   1214		chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
   1215		chan_tlv->header.len =
   1216			cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set));
   1217
   1218		memset(chan_tlv->chan_scan_param, 0x00,
   1219		       sizeof(struct mwifiex_chan_scan_param_set));
   1220		chan_tlv->chan_scan_param[0].chan_number =
   1221			(bss_desc->phy_param_set.ds_param_set.current_chan);
   1222		mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Chan=%d\n",
   1223			    chan_tlv->chan_scan_param[0].chan_number);
   1224
   1225		chan_tlv->chan_scan_param[0].radio_type =
   1226			mwifiex_band_to_radio_type((u8) bss_desc->bss_band);
   1227
   1228		mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Band=%d\n",
   1229			    chan_tlv->chan_scan_param[0].radio_type);
   1230		pos += sizeof(chan_tlv->header) +
   1231				sizeof(struct mwifiex_chan_scan_param_set);
   1232		cmd_append_size += sizeof(chan_tlv->header) +
   1233				sizeof(struct mwifiex_chan_scan_param_set);
   1234	}
   1235
   1236	if (priv->sec_info.wpa_enabled)
   1237		rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos);
   1238	if (rsn_ie_len == -1)
   1239		return -1;
   1240	cmd_append_size += rsn_ie_len;
   1241
   1242	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
   1243		cmd_append_size += mwifiex_cmd_append_11n_tlv(priv,
   1244			bss_desc, &pos);
   1245
   1246	/* Append vendor specific IE TLV */
   1247	cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv,
   1248			MWIFIEX_VSIE_MASK_ADHOC, &pos);
   1249
   1250	cmd->size = cpu_to_le16
   1251		((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join)
   1252			+ S_DS_GEN + cmd_append_size));
   1253
   1254	adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap);
   1255
   1256	return 0;
   1257}
   1258
   1259/*
   1260 * This function handles the command response of ad-hoc start and
   1261 * ad-hoc join.
   1262 *
   1263 * The function generates a device-connected event to notify
   1264 * the applications, in case of successful ad-hoc start/join, and
   1265 * saves the beacon buffer.
   1266 */
   1267int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
   1268			      struct host_cmd_ds_command *resp)
   1269{
   1270	int ret = 0;
   1271	struct mwifiex_adapter *adapter = priv->adapter;
   1272	struct host_cmd_ds_802_11_ad_hoc_start_result *start_result =
   1273				&resp->params.start_result;
   1274	struct host_cmd_ds_802_11_ad_hoc_join_result *join_result =
   1275				&resp->params.join_result;
   1276	struct mwifiex_bssdescriptor *bss_desc;
   1277	u16 cmd = le16_to_cpu(resp->command);
   1278	u8 result;
   1279
   1280	if (!priv->attempted_bss_desc) {
   1281		mwifiex_dbg(priv->adapter, ERROR,
   1282			    "ADHOC_RESP: failed, association terminated by host\n");
   1283		goto done;
   1284	}
   1285
   1286	if (cmd == HostCmd_CMD_802_11_AD_HOC_START)
   1287		result = start_result->result;
   1288	else
   1289		result = join_result->result;
   1290
   1291	bss_desc = priv->attempted_bss_desc;
   1292
   1293	/* Join result code 0 --> SUCCESS */
   1294	if (result) {
   1295		mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n");
   1296		if (priv->media_connected)
   1297			mwifiex_reset_connect_state(priv, result, true);
   1298
   1299		memset(&priv->curr_bss_params.bss_descriptor,
   1300		       0x00, sizeof(struct mwifiex_bssdescriptor));
   1301
   1302		ret = -1;
   1303		goto done;
   1304	}
   1305
   1306	/* Send a Media Connected event, according to the Spec */
   1307	priv->media_connected = true;
   1308
   1309	if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
   1310		mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_S_RESP %s\n",
   1311			    bss_desc->ssid.ssid);
   1312
   1313		/* Update the created network descriptor with the new BSSID */
   1314		memcpy(bss_desc->mac_address,
   1315		       start_result->bssid, ETH_ALEN);
   1316
   1317		priv->adhoc_state = ADHOC_STARTED;
   1318	} else {
   1319		/*
   1320		 * Now the join cmd should be successful.
   1321		 * If BSSID has changed use SSID to compare instead of BSSID
   1322		 */
   1323		mwifiex_dbg(priv->adapter, INFO,
   1324			    "info: ADHOC_J_RESP %s\n",
   1325			    bss_desc->ssid.ssid);
   1326
   1327		/*
   1328		 * Make a copy of current BSSID descriptor, only needed for
   1329		 * join since the current descriptor is already being used
   1330		 * for adhoc start
   1331		 */
   1332		memcpy(&priv->curr_bss_params.bss_descriptor,
   1333		       bss_desc, sizeof(struct mwifiex_bssdescriptor));
   1334
   1335		priv->adhoc_state = ADHOC_JOINED;
   1336	}
   1337
   1338	mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: channel = %d\n",
   1339		    priv->adhoc_channel);
   1340	mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: BSSID = %pM\n",
   1341		    priv->curr_bss_params.bss_descriptor.mac_address);
   1342
   1343	if (!netif_carrier_ok(priv->netdev))
   1344		netif_carrier_on(priv->netdev);
   1345	mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
   1346
   1347	mwifiex_save_curr_bcn(priv);
   1348
   1349done:
   1350	/* Need to indicate IOCTL complete */
   1351	if (adapter->curr_cmd->wait_q_enabled) {
   1352		if (ret)
   1353			adapter->cmd_wait_q.status = -1;
   1354		else
   1355			adapter->cmd_wait_q.status = 0;
   1356
   1357	}
   1358
   1359	return ret;
   1360}
   1361
   1362/*
   1363 * This function associates to a specific BSS discovered in a scan.
   1364 *
   1365 * It clears any past association response stored for application
   1366 * retrieval and calls the command preparation routine to send the
   1367 * command to firmware.
   1368 */
   1369int mwifiex_associate(struct mwifiex_private *priv,
   1370		      struct mwifiex_bssdescriptor *bss_desc)
   1371{
   1372	/* Return error if the adapter is not STA role or table entry
   1373	 * is not marked as infra.
   1374	 */
   1375	if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) ||
   1376	    (bss_desc->bss_mode != NL80211_IFTYPE_STATION))
   1377		return -1;
   1378
   1379	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
   1380	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
   1381	    priv->adapter->config_bands & BAND_AAC)
   1382		mwifiex_set_11ac_ba_params(priv);
   1383	else
   1384		mwifiex_set_ba_params(priv);
   1385
   1386	/* Clear any past association response stored for application
   1387	   retrieval */
   1388	priv->assoc_rsp_size = 0;
   1389
   1390	return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE,
   1391				HostCmd_ACT_GEN_SET, 0, bss_desc, true);
   1392}
   1393
   1394/*
   1395 * This function starts an ad-hoc network.
   1396 *
   1397 * It calls the command preparation routine to send the command to firmware.
   1398 */
   1399int
   1400mwifiex_adhoc_start(struct mwifiex_private *priv,
   1401		    struct cfg80211_ssid *adhoc_ssid)
   1402{
   1403	mwifiex_dbg(priv->adapter, INFO, "info: Adhoc Channel = %d\n",
   1404		    priv->adhoc_channel);
   1405	mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.channel = %d\n",
   1406		    priv->curr_bss_params.bss_descriptor.channel);
   1407	mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.band = %d\n",
   1408		    priv->curr_bss_params.band);
   1409
   1410	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
   1411	    priv->adapter->config_bands & BAND_AAC)
   1412		mwifiex_set_11ac_ba_params(priv);
   1413	else
   1414		mwifiex_set_ba_params(priv);
   1415
   1416	return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START,
   1417				HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true);
   1418}
   1419
   1420/*
   1421 * This function joins an ad-hoc network found in a previous scan.
   1422 *
   1423 * It calls the command preparation routine to send the command to firmware,
   1424 * if already not connected to the requested SSID.
   1425 */
   1426int mwifiex_adhoc_join(struct mwifiex_private *priv,
   1427		       struct mwifiex_bssdescriptor *bss_desc)
   1428{
   1429	mwifiex_dbg(priv->adapter, INFO,
   1430		    "info: adhoc join: curr_bss ssid =%s\n",
   1431		    priv->curr_bss_params.bss_descriptor.ssid.ssid);
   1432	mwifiex_dbg(priv->adapter, INFO,
   1433		    "info: adhoc join: curr_bss ssid_len =%u\n",
   1434		    priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
   1435	mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid =%s\n",
   1436		    bss_desc->ssid.ssid);
   1437	mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid_len =%u\n",
   1438		    bss_desc->ssid.ssid_len);
   1439
   1440	/* Check if the requested SSID is already joined */
   1441	if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len &&
   1442	    !mwifiex_ssid_cmp(&bss_desc->ssid,
   1443			      &priv->curr_bss_params.bss_descriptor.ssid) &&
   1444	    (priv->curr_bss_params.bss_descriptor.bss_mode ==
   1445							NL80211_IFTYPE_ADHOC)) {
   1446		mwifiex_dbg(priv->adapter, INFO,
   1447			    "info: ADHOC_J_CMD: new ad-hoc SSID\t"
   1448			    "is the same as current; not attempting to re-join\n");
   1449		return -1;
   1450	}
   1451
   1452	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
   1453	    !bss_desc->disable_11n && !bss_desc->disable_11ac &&
   1454	    priv->adapter->config_bands & BAND_AAC)
   1455		mwifiex_set_11ac_ba_params(priv);
   1456	else
   1457		mwifiex_set_ba_params(priv);
   1458
   1459	mwifiex_dbg(priv->adapter, INFO,
   1460		    "info: curr_bss_params.channel = %d\n",
   1461		    priv->curr_bss_params.bss_descriptor.channel);
   1462	mwifiex_dbg(priv->adapter, INFO,
   1463		    "info: curr_bss_params.band = %c\n",
   1464		    priv->curr_bss_params.band);
   1465
   1466	return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
   1467				HostCmd_ACT_GEN_SET, 0, bss_desc, true);
   1468}
   1469
   1470/*
   1471 * This function deauthenticates/disconnects from infra network by sending
   1472 * deauthentication request.
   1473 */
   1474static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
   1475{
   1476	u8 mac_address[ETH_ALEN];
   1477	int ret;
   1478
   1479	if (!mac || is_zero_ether_addr(mac))
   1480		memcpy(mac_address,
   1481		       priv->curr_bss_params.bss_descriptor.mac_address,
   1482		       ETH_ALEN);
   1483	else
   1484		memcpy(mac_address, mac, ETH_ALEN);
   1485
   1486	ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
   1487			       HostCmd_ACT_GEN_SET, 0, mac_address, true);
   1488
   1489	return ret;
   1490}
   1491
   1492/*
   1493 * This function deauthenticates/disconnects from a BSS.
   1494 *
   1495 * In case of infra made, it sends deauthentication request, and
   1496 * in case of ad-hoc mode, a stop network request is sent to the firmware.
   1497 * In AP mode, a command to stop bss is sent to firmware.
   1498 */
   1499int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
   1500{
   1501	int ret = 0;
   1502
   1503	if (!priv->media_connected)
   1504		return 0;
   1505
   1506	switch (priv->bss_mode) {
   1507	case NL80211_IFTYPE_STATION:
   1508	case NL80211_IFTYPE_P2P_CLIENT:
   1509		ret = mwifiex_deauthenticate_infra(priv, mac);
   1510		if (ret)
   1511			cfg80211_disconnected(priv->netdev, 0, NULL, 0,
   1512					      true, GFP_KERNEL);
   1513		break;
   1514	case NL80211_IFTYPE_ADHOC:
   1515		return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP,
   1516					HostCmd_ACT_GEN_SET, 0, NULL, true);
   1517	case NL80211_IFTYPE_AP:
   1518		return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
   1519					HostCmd_ACT_GEN_SET, 0, NULL, true);
   1520	default:
   1521		break;
   1522	}
   1523
   1524	return ret;
   1525}
   1526
   1527/* This function deauthenticates/disconnects from all BSS. */
   1528void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter)
   1529{
   1530	struct mwifiex_private *priv;
   1531	int i;
   1532
   1533	for (i = 0; i < adapter->priv_num; i++) {
   1534		priv = adapter->priv[i];
   1535		if (priv)
   1536			mwifiex_deauthenticate(priv, NULL);
   1537	}
   1538}
   1539EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all);
   1540
   1541/*
   1542 * This function converts band to radio type used in channel TLV.
   1543 */
   1544u8
   1545mwifiex_band_to_radio_type(u8 band)
   1546{
   1547	switch (band) {
   1548	case BAND_A:
   1549	case BAND_AN:
   1550	case BAND_A | BAND_AN:
   1551	case BAND_A | BAND_AN | BAND_AAC:
   1552		return HostCmd_SCAN_RADIO_TYPE_A;
   1553	case BAND_B:
   1554	case BAND_G:
   1555	case BAND_B | BAND_G:
   1556	default:
   1557		return HostCmd_SCAN_RADIO_TYPE_BG;
   1558	}
   1559}