PageRenderTime 115ms CodeModel.GetById 18ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/net/wireless/mwifiex/scan.c

http://github.com/mirrors/linux
C | 2132 lines | 1448 code | 259 blank | 425 comment | 214 complexity | 4c3120a82507d13bbd66d183bc574351 MD5 | raw file
   1/*
   2 * Marvell Wireless LAN device driver: scan ioctl and command handling
   3 *
   4 * Copyright (C) 2011, Marvell International Ltd.
   5 *
   6 * This software file (the "File") is distributed by Marvell International
   7 * Ltd. 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 "11n.h"
  26#include "cfg80211.h"
  27
  28/* The maximum number of channels the firmware can scan per command */
  29#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN   14
  30
  31#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD	4
  32#define MWIFIEX_LIMIT_1_CHANNEL_PER_SCAN_CMD	15
  33#define MWIFIEX_LIMIT_2_CHANNELS_PER_SCAN_CMD	27
  34#define MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD	35
  35
  36/* Memory needed to store a max sized Channel List TLV for a firmware scan */
  37#define CHAN_TLV_MAX_SIZE  (sizeof(struct mwifiex_ie_types_header)         \
  38				+ (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN     \
  39				*sizeof(struct mwifiex_chan_scan_param_set)))
  40
  41/* Memory needed to store supported rate */
  42#define RATE_TLV_MAX_SIZE   (sizeof(struct mwifiex_ie_types_rates_param_set) \
  43				+ HOSTCMD_SUPPORTED_RATES)
  44
  45/* Memory needed to store a max number/size WildCard SSID TLV for a firmware
  46	scan */
  47#define WILDCARD_SSID_TLV_MAX_SIZE  \
  48	(MWIFIEX_MAX_SSID_LIST_LENGTH *					\
  49		(sizeof(struct mwifiex_ie_types_wildcard_ssid_params)	\
  50			+ IEEE80211_MAX_SSID_LEN))
  51
  52/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
  53#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config)        \
  54				+ sizeof(struct mwifiex_ie_types_num_probes)   \
  55				+ sizeof(struct mwifiex_ie_types_htcap)       \
  56				+ CHAN_TLV_MAX_SIZE                 \
  57				+ RATE_TLV_MAX_SIZE                 \
  58				+ WILDCARD_SSID_TLV_MAX_SIZE)
  59
  60
  61union mwifiex_scan_cmd_config_tlv {
  62	/* Scan configuration (variable length) */
  63	struct mwifiex_scan_cmd_config config;
  64	/* Max allocated block */
  65	u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
  66};
  67
  68enum cipher_suite {
  69	CIPHER_SUITE_TKIP,
  70	CIPHER_SUITE_CCMP,
  71	CIPHER_SUITE_MAX
  72};
  73static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
  74	{ 0x00, 0x50, 0xf2, 0x02 },	/* TKIP */
  75	{ 0x00, 0x50, 0xf2, 0x04 },	/* AES  */
  76};
  77static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
  78	{ 0x00, 0x0f, 0xac, 0x02 },	/* TKIP */
  79	{ 0x00, 0x0f, 0xac, 0x04 },	/* AES  */
  80};
  81
  82/*
  83 * This function parses a given IE for a given OUI.
  84 *
  85 * This is used to parse a WPA/RSN IE to find if it has
  86 * a given oui in PTK.
  87 */
  88static u8
  89mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
  90{
  91	u8 count;
  92
  93	count = iebody->ptk_cnt[0];
  94
  95	/* There could be multiple OUIs for PTK hence
  96	   1) Take the length.
  97	   2) Check all the OUIs for AES.
  98	   3) If one of them is AES then pass success. */
  99	while (count) {
 100		if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
 101			return MWIFIEX_OUI_PRESENT;
 102
 103		--count;
 104		if (count)
 105			iebody = (struct ie_body *) ((u8 *) iebody +
 106						sizeof(iebody->ptk_body));
 107	}
 108
 109	pr_debug("info: %s: OUI is not found in PTK\n", __func__);
 110	return MWIFIEX_OUI_NOT_PRESENT;
 111}
 112
 113/*
 114 * This function checks if a given OUI is present in a RSN IE.
 115 *
 116 * The function first checks if a RSN IE is present or not in the
 117 * BSS descriptor. It tries to locate the OUI only if such an IE is
 118 * present.
 119 */
 120static u8
 121mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
 122{
 123	u8 *oui;
 124	struct ie_body *iebody;
 125	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 126
 127	if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).
 128					ieee_hdr.element_id == WLAN_EID_RSN))) {
 129		iebody = (struct ie_body *)
 130			 (((u8 *) bss_desc->bcn_rsn_ie->data) +
 131			  RSN_GTK_OUI_OFFSET);
 132		oui = &mwifiex_rsn_oui[cipher][0];
 133		ret = mwifiex_search_oui_in_ie(iebody, oui);
 134		if (ret)
 135			return ret;
 136	}
 137	return ret;
 138}
 139
 140/*
 141 * This function checks if a given OUI is present in a WPA IE.
 142 *
 143 * The function first checks if a WPA IE is present or not in the
 144 * BSS descriptor. It tries to locate the OUI only if such an IE is
 145 * present.
 146 */
 147static u8
 148mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
 149{
 150	u8 *oui;
 151	struct ie_body *iebody;
 152	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 153
 154	if (((bss_desc->bcn_wpa_ie) &&
 155	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
 156	      WLAN_EID_VENDOR_SPECIFIC))) {
 157		iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
 158		oui = &mwifiex_wpa_oui[cipher][0];
 159		ret = mwifiex_search_oui_in_ie(iebody, oui);
 160		if (ret)
 161			return ret;
 162	}
 163	return ret;
 164}
 165
 166/*
 167 * This function compares two SSIDs and checks if they match.
 168 */
 169s32
 170mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
 171{
 172	if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
 173		return -1;
 174	return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
 175}
 176
 177/*
 178 * This function checks if wapi is enabled in driver and scanned network is
 179 * compatible with it.
 180 */
 181static bool
 182mwifiex_is_bss_wapi(struct mwifiex_private *priv,
 183		    struct mwifiex_bssdescriptor *bss_desc)
 184{
 185	if (priv->sec_info.wapi_enabled &&
 186	    (bss_desc->bcn_wapi_ie &&
 187	     ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id ==
 188			WLAN_EID_BSS_AC_ACCESS_DELAY))) {
 189		return true;
 190	}
 191	return false;
 192}
 193
 194/*
 195 * This function checks if driver is configured with no security mode and
 196 * scanned network is compatible with it.
 197 */
 198static bool
 199mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
 200		      struct mwifiex_bssdescriptor *bss_desc)
 201{
 202	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 203	    !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
 204		((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
 205		 WLAN_EID_VENDOR_SPECIFIC)) &&
 206	    ((!bss_desc->bcn_rsn_ie) ||
 207		((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
 208		 WLAN_EID_RSN)) &&
 209	    !priv->sec_info.encryption_mode && !bss_desc->privacy) {
 210		return true;
 211	}
 212	return false;
 213}
 214
 215/*
 216 * This function checks if static WEP is enabled in driver and scanned network
 217 * is compatible with it.
 218 */
 219static bool
 220mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
 221			  struct mwifiex_bssdescriptor *bss_desc)
 222{
 223	if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 224	    !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
 225		return true;
 226	}
 227	return false;
 228}
 229
 230/*
 231 * This function checks if wpa is enabled in driver and scanned network is
 232 * compatible with it.
 233 */
 234static bool
 235mwifiex_is_bss_wpa(struct mwifiex_private *priv,
 236		   struct mwifiex_bssdescriptor *bss_desc)
 237{
 238	if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
 239	    !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
 240	    ((*(bss_desc->bcn_wpa_ie)).
 241	     vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
 242	   /*
 243	    * Privacy bit may NOT be set in some APs like
 244	    * LinkSys WRT54G && bss_desc->privacy
 245	    */
 246	 ) {
 247		dev_dbg(priv->adapter->dev, "info: %s: WPA:"
 248			" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
 249			"EncMode=%#x privacy=%#x\n", __func__,
 250			(bss_desc->bcn_wpa_ie) ?
 251			(*(bss_desc->bcn_wpa_ie)).
 252			vend_hdr.element_id : 0,
 253			(bss_desc->bcn_rsn_ie) ?
 254			(*(bss_desc->bcn_rsn_ie)).
 255			ieee_hdr.element_id : 0,
 256			(priv->sec_info.wep_enabled) ? "e" : "d",
 257			(priv->sec_info.wpa_enabled) ? "e" : "d",
 258			(priv->sec_info.wpa2_enabled) ? "e" : "d",
 259			priv->sec_info.encryption_mode,
 260			bss_desc->privacy);
 261		return true;
 262	}
 263	return false;
 264}
 265
 266/*
 267 * This function checks if wpa2 is enabled in driver and scanned network is
 268 * compatible with it.
 269 */
 270static bool
 271mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
 272		    struct mwifiex_bssdescriptor *bss_desc)
 273{
 274	if (!priv->sec_info.wep_enabled &&
 275	    !priv->sec_info.wpa_enabled &&
 276	    priv->sec_info.wpa2_enabled &&
 277	    ((bss_desc->bcn_rsn_ie) &&
 278	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) {
 279		/*
 280		 * Privacy bit may NOT be set in some APs like
 281		 * LinkSys WRT54G && bss_desc->privacy
 282		 */
 283		dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
 284			" wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
 285			"EncMode=%#x privacy=%#x\n", __func__,
 286			(bss_desc->bcn_wpa_ie) ?
 287			(*(bss_desc->bcn_wpa_ie)).
 288			vend_hdr.element_id : 0,
 289			(bss_desc->bcn_rsn_ie) ?
 290			(*(bss_desc->bcn_rsn_ie)).
 291			ieee_hdr.element_id : 0,
 292			(priv->sec_info.wep_enabled) ? "e" : "d",
 293			(priv->sec_info.wpa_enabled) ? "e" : "d",
 294			(priv->sec_info.wpa2_enabled) ? "e" : "d",
 295			priv->sec_info.encryption_mode,
 296			bss_desc->privacy);
 297		return true;
 298	}
 299	return false;
 300}
 301
 302/*
 303 * This function checks if adhoc AES is enabled in driver and scanned network is
 304 * compatible with it.
 305 */
 306static bool
 307mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
 308			 struct mwifiex_bssdescriptor *bss_desc)
 309{
 310	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 311	    !priv->sec_info.wpa2_enabled &&
 312	    ((!bss_desc->bcn_wpa_ie) ||
 313	     ((*(bss_desc->bcn_wpa_ie)).
 314	      vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
 315	    ((!bss_desc->bcn_rsn_ie) ||
 316	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
 317	    !priv->sec_info.encryption_mode && bss_desc->privacy) {
 318		return true;
 319	}
 320	return false;
 321}
 322
 323/*
 324 * This function checks if dynamic WEP is enabled in driver and scanned network
 325 * is compatible with it.
 326 */
 327static bool
 328mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
 329			   struct mwifiex_bssdescriptor *bss_desc)
 330{
 331	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 332	    !priv->sec_info.wpa2_enabled &&
 333	    ((!bss_desc->bcn_wpa_ie) ||
 334	     ((*(bss_desc->bcn_wpa_ie)).
 335	      vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
 336	    ((!bss_desc->bcn_rsn_ie) ||
 337	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
 338	    priv->sec_info.encryption_mode && bss_desc->privacy) {
 339		dev_dbg(priv->adapter->dev, "info: %s: dynamic "
 340			"WEP: wpa_ie=%#x wpa2_ie=%#x "
 341			"EncMode=%#x privacy=%#x\n",
 342			__func__,
 343			(bss_desc->bcn_wpa_ie) ?
 344			(*(bss_desc->bcn_wpa_ie)).
 345			vend_hdr.element_id : 0,
 346			(bss_desc->bcn_rsn_ie) ?
 347			(*(bss_desc->bcn_rsn_ie)).
 348			ieee_hdr.element_id : 0,
 349			priv->sec_info.encryption_mode,
 350			bss_desc->privacy);
 351		return true;
 352	}
 353	return false;
 354}
 355
 356/*
 357 * This function checks if a scanned network is compatible with the driver
 358 * settings.
 359 *
 360 *   WEP     WPA    WPA2   ad-hoc encrypt                  Network
 361 * enabled enabled enabled  AES    mode   Privacy WPA WPA2 Compatible
 362 *    0       0       0      0     NONE      0     0   0   yes No security
 363 *    0       1       0      0      x        1x    1   x   yes WPA (disable
 364 *                                                         HT if no AES)
 365 *    0       0       1      0      x        1x    x   1   yes WPA2 (disable
 366 *                                                         HT if no AES)
 367 *    0       0       0      1     NONE      1     0   0   yes Ad-hoc AES
 368 *    1       0       0      0     NONE      1     0   0   yes Static WEP
 369 *                                                         (disable HT)
 370 *    0       0       0      0    !=NONE     1     0   0   yes Dynamic WEP
 371 *
 372 * Compatibility is not matched while roaming, except for mode.
 373 */
 374static s32
 375mwifiex_is_network_compatible(struct mwifiex_private *priv,
 376			      struct mwifiex_bssdescriptor *bss_desc, u32 mode)
 377{
 378	struct mwifiex_adapter *adapter = priv->adapter;
 379
 380	bss_desc->disable_11n = false;
 381
 382	/* Don't check for compatibility if roaming */
 383	if (priv->media_connected &&
 384	    (priv->bss_mode == NL80211_IFTYPE_STATION) &&
 385	    (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
 386		return 0;
 387
 388	if (priv->wps.session_enable) {
 389		dev_dbg(adapter->dev,
 390			"info: return success directly in WPS period\n");
 391		return 0;
 392	}
 393
 394	if (bss_desc->chan_sw_ie_present) {
 395		dev_err(adapter->dev,
 396			"Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
 397		return -1;
 398	}
 399
 400	if (mwifiex_is_bss_wapi(priv, bss_desc)) {
 401		dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
 402		return 0;
 403	}
 404
 405	if (bss_desc->bss_mode == mode) {
 406		if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
 407			/* No security */
 408			return 0;
 409		} else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
 410			/* Static WEP enabled */
 411			dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
 412			bss_desc->disable_11n = true;
 413			return 0;
 414		} else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
 415			/* WPA enabled */
 416			if (((priv->adapter->config_bands & BAND_GN ||
 417			      priv->adapter->config_bands & BAND_AN) &&
 418			     bss_desc->bcn_ht_cap) &&
 419			    !mwifiex_is_wpa_oui_present(bss_desc,
 420							 CIPHER_SUITE_CCMP)) {
 421
 422				if (mwifiex_is_wpa_oui_present
 423						(bss_desc, CIPHER_SUITE_TKIP)) {
 424					dev_dbg(adapter->dev,
 425						"info: Disable 11n if AES "
 426						"is not supported by AP\n");
 427					bss_desc->disable_11n = true;
 428				} else {
 429					return -1;
 430				}
 431			}
 432			return 0;
 433		} else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
 434			/* WPA2 enabled */
 435			if (((priv->adapter->config_bands & BAND_GN ||
 436			      priv->adapter->config_bands & BAND_AN) &&
 437			     bss_desc->bcn_ht_cap) &&
 438			    !mwifiex_is_rsn_oui_present(bss_desc,
 439							CIPHER_SUITE_CCMP)) {
 440
 441				if (mwifiex_is_rsn_oui_present
 442						(bss_desc, CIPHER_SUITE_TKIP)) {
 443					dev_dbg(adapter->dev,
 444						"info: Disable 11n if AES "
 445						"is not supported by AP\n");
 446					bss_desc->disable_11n = true;
 447				} else {
 448					return -1;
 449				}
 450			}
 451			return 0;
 452		} else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
 453			/* Ad-hoc AES enabled */
 454			return 0;
 455		} else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
 456			/* Dynamic WEP enabled */
 457			return 0;
 458		}
 459
 460		/* Security doesn't match */
 461		dev_dbg(adapter->dev,
 462			"info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s "
 463			"WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", __func__,
 464			(bss_desc->bcn_wpa_ie) ?
 465			(*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id : 0,
 466			(bss_desc->bcn_rsn_ie) ?
 467			(*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id : 0,
 468			(priv->sec_info.wep_enabled) ? "e" : "d",
 469			(priv->sec_info.wpa_enabled) ? "e" : "d",
 470			(priv->sec_info.wpa2_enabled) ? "e" : "d",
 471			priv->sec_info.encryption_mode, bss_desc->privacy);
 472		return -1;
 473	}
 474
 475	/* Mode doesn't match */
 476	return -1;
 477}
 478
 479/*
 480 * This function creates a channel list for the driver to scan, based
 481 * on region/band information.
 482 *
 483 * This routine is used for any scan that is not provided with a
 484 * specific channel list to scan.
 485 */
 486static int
 487mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
 488				 const struct mwifiex_user_scan_cfg
 489							*user_scan_in,
 490				 struct mwifiex_chan_scan_param_set
 491							*scan_chan_list,
 492				 u8 filtered_scan)
 493{
 494	enum ieee80211_band band;
 495	struct ieee80211_supported_band *sband;
 496	struct ieee80211_channel *ch;
 497	struct mwifiex_adapter *adapter = priv->adapter;
 498	int chan_idx = 0, i;
 499
 500	for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) {
 501
 502		if (!priv->wdev->wiphy->bands[band])
 503			continue;
 504
 505		sband = priv->wdev->wiphy->bands[band];
 506
 507		for (i = 0; (i < sband->n_channels) ; i++) {
 508			ch = &sband->channels[i];
 509			if (ch->flags & IEEE80211_CHAN_DISABLED)
 510				continue;
 511			scan_chan_list[chan_idx].radio_type = band;
 512
 513			if (user_scan_in &&
 514			    user_scan_in->chan_list[0].scan_time)
 515				scan_chan_list[chan_idx].max_scan_time =
 516					cpu_to_le16((u16) user_scan_in->
 517					chan_list[0].scan_time);
 518			else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 519				scan_chan_list[chan_idx].max_scan_time =
 520					cpu_to_le16(adapter->passive_scan_time);
 521			else
 522				scan_chan_list[chan_idx].max_scan_time =
 523					cpu_to_le16(adapter->active_scan_time);
 524
 525			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
 526				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 527					|= MWIFIEX_PASSIVE_SCAN;
 528			else
 529				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 530					&= ~MWIFIEX_PASSIVE_SCAN;
 531			scan_chan_list[chan_idx].chan_number =
 532							(u32) ch->hw_value;
 533			if (filtered_scan) {
 534				scan_chan_list[chan_idx].max_scan_time =
 535				cpu_to_le16(adapter->specific_scan_time);
 536				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 537					|= MWIFIEX_DISABLE_CHAN_FILT;
 538			}
 539			chan_idx++;
 540		}
 541
 542	}
 543	return chan_idx;
 544}
 545
 546/* This function appends rate TLV to scan config command. */
 547static int
 548mwifiex_append_rate_tlv(struct mwifiex_private *priv,
 549			struct mwifiex_scan_cmd_config *scan_cfg_out,
 550			u8 radio)
 551{
 552	struct mwifiex_ie_types_rates_param_set *rates_tlv;
 553	u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
 554	u32 rates_size;
 555
 556	memset(rates, 0, sizeof(rates));
 557
 558	tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
 559
 560	if (priv->scan_request)
 561		rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
 562							     radio);
 563	else
 564		rates_size = mwifiex_get_supported_rates(priv, rates);
 565
 566	dev_dbg(priv->adapter->dev, "info: SCAN_CMD: Rates size = %d\n",
 567		rates_size);
 568	rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
 569	rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
 570	rates_tlv->header.len = cpu_to_le16((u16) rates_size);
 571	memcpy(rates_tlv->rates, rates, rates_size);
 572	scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
 573
 574	return rates_size;
 575}
 576
 577/*
 578 * This function constructs and sends multiple scan config commands to
 579 * the firmware.
 580 *
 581 * Previous routines in the code flow have created a scan command configuration
 582 * with any requested TLVs.  This function splits the channel TLV into maximum
 583 * channels supported per scan lists and sends the portion of the channel TLV,
 584 * along with the other TLVs, to the firmware.
 585 */
 586static int
 587mwifiex_scan_channel_list(struct mwifiex_private *priv,
 588			  u32 max_chan_per_scan, u8 filtered_scan,
 589			  struct mwifiex_scan_cmd_config *scan_cfg_out,
 590			  struct mwifiex_ie_types_chan_list_param_set
 591			  *chan_tlv_out,
 592			  struct mwifiex_chan_scan_param_set *scan_chan_list)
 593{
 594	int ret = 0;
 595	struct mwifiex_chan_scan_param_set *tmp_chan_list;
 596	struct mwifiex_chan_scan_param_set *start_chan;
 597
 598	u32 tlv_idx, rates_size;
 599	u32 total_scan_time;
 600	u32 done_early;
 601	u8 radio_type;
 602
 603	if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
 604		dev_dbg(priv->adapter->dev,
 605			"info: Scan: Null detect: %p, %p, %p\n",
 606		       scan_cfg_out, chan_tlv_out, scan_chan_list);
 607		return -1;
 608	}
 609
 610	/* Check csa channel expiry before preparing scan list */
 611	mwifiex_11h_get_csa_closed_channel(priv);
 612
 613	chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
 614
 615	/* Set the temp channel struct pointer to the start of the desired
 616	   list */
 617	tmp_chan_list = scan_chan_list;
 618
 619	/* Loop through the desired channel list, sending a new firmware scan
 620	   commands for each max_chan_per_scan channels (or for 1,6,11
 621	   individually if configured accordingly) */
 622	while (tmp_chan_list->chan_number) {
 623
 624		tlv_idx = 0;
 625		total_scan_time = 0;
 626		radio_type = 0;
 627		chan_tlv_out->header.len = 0;
 628		start_chan = tmp_chan_list;
 629		done_early = false;
 630
 631		/*
 632		 * Construct the Channel TLV for the scan command.  Continue to
 633		 * insert channel TLVs until:
 634		 *   - the tlv_idx hits the maximum configured per scan command
 635		 *   - the next channel to insert is 0 (end of desired channel
 636		 *     list)
 637		 *   - done_early is set (controlling individual scanning of
 638		 *     1,6,11)
 639		 */
 640		while (tlv_idx < max_chan_per_scan &&
 641		       tmp_chan_list->chan_number && !done_early) {
 642
 643			if (tmp_chan_list->chan_number == priv->csa_chan) {
 644				tmp_chan_list++;
 645				continue;
 646			}
 647
 648			radio_type = tmp_chan_list->radio_type;
 649			dev_dbg(priv->adapter->dev,
 650				"info: Scan: Chan(%3d), Radio(%d),"
 651				" Mode(%d, %d), Dur(%d)\n",
 652				tmp_chan_list->chan_number,
 653				tmp_chan_list->radio_type,
 654				tmp_chan_list->chan_scan_mode_bitmap
 655				& MWIFIEX_PASSIVE_SCAN,
 656				(tmp_chan_list->chan_scan_mode_bitmap
 657				 & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
 658				le16_to_cpu(tmp_chan_list->max_scan_time));
 659
 660			/* Copy the current channel TLV to the command being
 661			   prepared */
 662			memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
 663			       tmp_chan_list,
 664			       sizeof(chan_tlv_out->chan_scan_param));
 665
 666			/* Increment the TLV header length by the size
 667			   appended */
 668			le16_add_cpu(&chan_tlv_out->header.len,
 669				     sizeof(chan_tlv_out->chan_scan_param));
 670
 671			/*
 672			 * The tlv buffer length is set to the number of bytes
 673			 * of the between the channel tlv pointer and the start
 674			 * of the tlv buffer.  This compensates for any TLVs
 675			 * that were appended before the channel list.
 676			 */
 677			scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
 678							scan_cfg_out->tlv_buf);
 679
 680			/* Add the size of the channel tlv header and the data
 681			   length */
 682			scan_cfg_out->tlv_buf_len +=
 683				(sizeof(chan_tlv_out->header)
 684				 + le16_to_cpu(chan_tlv_out->header.len));
 685
 686			/* Increment the index to the channel tlv we are
 687			   constructing */
 688			tlv_idx++;
 689
 690			/* Count the total scan time per command */
 691			total_scan_time +=
 692				le16_to_cpu(tmp_chan_list->max_scan_time);
 693
 694			done_early = false;
 695
 696			/* Stop the loop if the *current* channel is in the
 697			   1,6,11 set and we are not filtering on a BSSID
 698			   or SSID. */
 699			if (!filtered_scan &&
 700			    (tmp_chan_list->chan_number == 1 ||
 701			     tmp_chan_list->chan_number == 6 ||
 702			     tmp_chan_list->chan_number == 11))
 703				done_early = true;
 704
 705			/* Increment the tmp pointer to the next channel to
 706			   be scanned */
 707			tmp_chan_list++;
 708
 709			/* Stop the loop if the *next* channel is in the 1,6,11
 710			   set.  This will cause it to be the only channel
 711			   scanned on the next interation */
 712			if (!filtered_scan &&
 713			    (tmp_chan_list->chan_number == 1 ||
 714			     tmp_chan_list->chan_number == 6 ||
 715			     tmp_chan_list->chan_number == 11))
 716				done_early = true;
 717		}
 718
 719		/* The total scan time should be less than scan command timeout
 720		   value */
 721		if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
 722			dev_err(priv->adapter->dev, "total scan time %dms"
 723				" is over limit (%dms), scan skipped\n",
 724				total_scan_time, MWIFIEX_MAX_TOTAL_SCAN_TIME);
 725			ret = -1;
 726			break;
 727		}
 728
 729		rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
 730						     radio_type);
 731
 732		priv->adapter->scan_channels = start_chan;
 733
 734		/* Send the scan command to the firmware with the specified
 735		   cfg */
 736		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN,
 737					     HostCmd_ACT_GEN_SET, 0,
 738					     scan_cfg_out);
 739
 740		/* rate IE is updated per scan command but same starting
 741		 * pointer is used each time so that rate IE from earlier
 742		 * scan_cfg_out->buf is overwritten with new one.
 743		 */
 744		scan_cfg_out->tlv_buf_len -=
 745			    sizeof(struct mwifiex_ie_types_header) + rates_size;
 746
 747		if (ret)
 748			break;
 749	}
 750
 751	if (ret)
 752		return -1;
 753
 754	return 0;
 755}
 756
 757/*
 758 * This function constructs a scan command configuration structure to use
 759 * in scan commands.
 760 *
 761 * Application layer or other functions can invoke network scanning
 762 * with a scan configuration supplied in a user scan configuration structure.
 763 * This structure is used as the basis of one or many scan command configuration
 764 * commands that are sent to the command processing module and eventually to the
 765 * firmware.
 766 *
 767 * This function creates a scan command configuration structure  based on the
 768 * following user supplied parameters (if present):
 769 *      - SSID filter
 770 *      - BSSID filter
 771 *      - Number of Probes to be sent
 772 *      - Channel list
 773 *
 774 * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
 775 * If the number of probes is not set, adapter default setting is used.
 776 */
 777static void
 778mwifiex_config_scan(struct mwifiex_private *priv,
 779		    const struct mwifiex_user_scan_cfg *user_scan_in,
 780		    struct mwifiex_scan_cmd_config *scan_cfg_out,
 781		    struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
 782		    struct mwifiex_chan_scan_param_set *scan_chan_list,
 783		    u8 *max_chan_per_scan, u8 *filtered_scan,
 784		    u8 *scan_current_only)
 785{
 786	struct mwifiex_adapter *adapter = priv->adapter;
 787	struct mwifiex_ie_types_num_probes *num_probes_tlv;
 788	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
 789	u8 *tlv_pos;
 790	u32 num_probes;
 791	u32 ssid_len;
 792	u32 chan_idx;
 793	u32 chan_num;
 794	u32 scan_type;
 795	u16 scan_dur;
 796	u8 channel;
 797	u8 radio_type;
 798	int i;
 799	u8 ssid_filter;
 800	struct mwifiex_ie_types_htcap *ht_cap;
 801
 802	/* The tlv_buf_len is calculated for each scan command.  The TLVs added
 803	   in this routine will be preserved since the routine that sends the
 804	   command will append channelTLVs at *chan_list_out.  The difference
 805	   between the *chan_list_out and the tlv_buf start will be used to
 806	   calculate the size of anything we add in this routine. */
 807	scan_cfg_out->tlv_buf_len = 0;
 808
 809	/* Running tlv pointer.  Assigned to chan_list_out at end of function
 810	   so later routines know where channels can be added to the command
 811	   buf */
 812	tlv_pos = scan_cfg_out->tlv_buf;
 813
 814	/* Initialize the scan as un-filtered; the flag is later set to TRUE
 815	   below if a SSID or BSSID filter is sent in the command */
 816	*filtered_scan = false;
 817
 818	/* Initialize the scan as not being only on the current channel.  If
 819	   the channel list is customized, only contains one channel, and is
 820	   the active channel, this is set true and data flow is not halted. */
 821	*scan_current_only = false;
 822
 823	if (user_scan_in) {
 824
 825		/* Default the ssid_filter flag to TRUE, set false under
 826		   certain wildcard conditions and qualified by the existence
 827		   of an SSID list before marking the scan as filtered */
 828		ssid_filter = true;
 829
 830		/* Set the BSS type scan filter, use Adapter setting if
 831		   unset */
 832		scan_cfg_out->bss_mode =
 833			(user_scan_in->bss_mode ? (u8) user_scan_in->
 834			 bss_mode : (u8) adapter->scan_mode);
 835
 836		/* Set the number of probes to send, use Adapter setting
 837		   if unset */
 838		num_probes =
 839			(user_scan_in->num_probes ? user_scan_in->
 840			 num_probes : adapter->scan_probes);
 841
 842		/*
 843		 * Set the BSSID filter to the incoming configuration,
 844		 * if non-zero.  If not set, it will remain disabled
 845		 * (all zeros).
 846		 */
 847		memcpy(scan_cfg_out->specific_bssid,
 848		       user_scan_in->specific_bssid,
 849		       sizeof(scan_cfg_out->specific_bssid));
 850
 851		for (i = 0; i < user_scan_in->num_ssids; i++) {
 852			ssid_len = user_scan_in->ssid_list[i].ssid_len;
 853
 854			wildcard_ssid_tlv =
 855				(struct mwifiex_ie_types_wildcard_ssid_params *)
 856				tlv_pos;
 857			wildcard_ssid_tlv->header.type =
 858				cpu_to_le16(TLV_TYPE_WILDCARDSSID);
 859			wildcard_ssid_tlv->header.len = cpu_to_le16(
 860				(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
 861							 max_ssid_length)));
 862
 863			/*
 864			 * max_ssid_length = 0 tells firmware to perform
 865			 * specific scan for the SSID filled, whereas
 866			 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
 867			 * wildcard scan.
 868			 */
 869			if (ssid_len)
 870				wildcard_ssid_tlv->max_ssid_length = 0;
 871			else
 872				wildcard_ssid_tlv->max_ssid_length =
 873							IEEE80211_MAX_SSID_LEN;
 874
 875			memcpy(wildcard_ssid_tlv->ssid,
 876			       user_scan_in->ssid_list[i].ssid, ssid_len);
 877
 878			tlv_pos += (sizeof(wildcard_ssid_tlv->header)
 879				+ le16_to_cpu(wildcard_ssid_tlv->header.len));
 880
 881			dev_dbg(adapter->dev, "info: scan: ssid[%d]: %s, %d\n",
 882				i, wildcard_ssid_tlv->ssid,
 883				wildcard_ssid_tlv->max_ssid_length);
 884
 885			/* Empty wildcard ssid with a maxlen will match many or
 886			   potentially all SSIDs (maxlen == 32), therefore do
 887			   not treat the scan as
 888			   filtered. */
 889			if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
 890				ssid_filter = false;
 891		}
 892
 893		/*
 894		 *  The default number of channels sent in the command is low to
 895		 *  ensure the response buffer from the firmware does not
 896		 *  truncate scan results.  That is not an issue with an SSID
 897		 *  or BSSID filter applied to the scan results in the firmware.
 898		 */
 899		if ((i && ssid_filter) ||
 900		    !is_zero_ether_addr(scan_cfg_out->specific_bssid))
 901			*filtered_scan = true;
 902	} else {
 903		scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
 904		num_probes = adapter->scan_probes;
 905	}
 906
 907	/*
 908	 *  If a specific BSSID or SSID is used, the number of channels in the
 909	 *  scan command will be increased to the absolute maximum.
 910	 */
 911	if (*filtered_scan)
 912		*max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
 913	else
 914		*max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
 915
 916	/* If the input config or adapter has the number of Probes set,
 917	   add tlv */
 918	if (num_probes) {
 919
 920		dev_dbg(adapter->dev, "info: scan: num_probes = %d\n",
 921			num_probes);
 922
 923		num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
 924		num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
 925		num_probes_tlv->header.len =
 926			cpu_to_le16(sizeof(num_probes_tlv->num_probes));
 927		num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
 928
 929		tlv_pos += sizeof(num_probes_tlv->header) +
 930			le16_to_cpu(num_probes_tlv->header.len);
 931
 932	}
 933
 934	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
 935	    (priv->adapter->config_bands & BAND_GN ||
 936	     priv->adapter->config_bands & BAND_AN)) {
 937		ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
 938		memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
 939		ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
 940		ht_cap->header.len =
 941				cpu_to_le16(sizeof(struct ieee80211_ht_cap));
 942		radio_type =
 943			mwifiex_band_to_radio_type(priv->adapter->config_bands);
 944		mwifiex_fill_cap_info(priv, radio_type, ht_cap);
 945		tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
 946	}
 947
 948	/* Append vendor specific IE TLV */
 949	mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
 950
 951	/*
 952	 * Set the output for the channel TLV to the address in the tlv buffer
 953	 *   past any TLVs that were added in this function (SSID, num_probes).
 954	 *   Channel TLVs will be added past this for each scan command,
 955	 *   preserving the TLVs that were previously added.
 956	 */
 957	*chan_list_out =
 958		(struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
 959
 960	if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
 961
 962		dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n");
 963
 964		for (chan_idx = 0;
 965		     chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
 966		     user_scan_in->chan_list[chan_idx].chan_number;
 967		     chan_idx++) {
 968
 969			channel = user_scan_in->chan_list[chan_idx].chan_number;
 970			(scan_chan_list + chan_idx)->chan_number = channel;
 971
 972			radio_type =
 973				user_scan_in->chan_list[chan_idx].radio_type;
 974			(scan_chan_list + chan_idx)->radio_type = radio_type;
 975
 976			scan_type = user_scan_in->chan_list[chan_idx].scan_type;
 977
 978			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
 979				(scan_chan_list +
 980				 chan_idx)->chan_scan_mode_bitmap
 981					|= MWIFIEX_PASSIVE_SCAN;
 982			else
 983				(scan_chan_list +
 984				 chan_idx)->chan_scan_mode_bitmap
 985					&= ~MWIFIEX_PASSIVE_SCAN;
 986
 987			if (*filtered_scan)
 988				(scan_chan_list +
 989				 chan_idx)->chan_scan_mode_bitmap
 990					|= MWIFIEX_DISABLE_CHAN_FILT;
 991
 992			if (user_scan_in->chan_list[chan_idx].scan_time) {
 993				scan_dur = (u16) user_scan_in->
 994					chan_list[chan_idx].scan_time;
 995			} else {
 996				if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
 997					scan_dur = adapter->passive_scan_time;
 998				else if (*filtered_scan)
 999					scan_dur = adapter->specific_scan_time;
1000				else
1001					scan_dur = adapter->active_scan_time;
1002			}
1003
1004			(scan_chan_list + chan_idx)->min_scan_time =
1005				cpu_to_le16(scan_dur);
1006			(scan_chan_list + chan_idx)->max_scan_time =
1007				cpu_to_le16(scan_dur);
1008		}
1009
1010		/* Check if we are only scanning the current channel */
1011		if ((chan_idx == 1) &&
1012		    (user_scan_in->chan_list[0].chan_number ==
1013		     priv->curr_bss_params.bss_descriptor.channel)) {
1014			*scan_current_only = true;
1015			dev_dbg(adapter->dev,
1016				"info: Scan: Scanning current channel only\n");
1017		}
1018		chan_num = chan_idx;
1019	} else {
1020		dev_dbg(adapter->dev,
1021			"info: Scan: Creating full region channel list\n");
1022		chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in,
1023							    scan_chan_list,
1024							    *filtered_scan);
1025	}
1026
1027	/*
1028	 * In associated state we will reduce the number of channels scanned per
1029	 * scan command to avoid any traffic delay/loss. This number is decided
1030	 * based on total number of channels to be scanned due to constraints
1031	 * of command buffers.
1032	 */
1033	if (priv->media_connected) {
1034		if (chan_num < MWIFIEX_LIMIT_1_CHANNEL_PER_SCAN_CMD)
1035			*max_chan_per_scan = 1;
1036		else if (chan_num < MWIFIEX_LIMIT_2_CHANNELS_PER_SCAN_CMD)
1037			*max_chan_per_scan = 2;
1038		else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD)
1039			*max_chan_per_scan = 3;
1040		else
1041			*max_chan_per_scan = 4;
1042	}
1043}
1044
1045/*
1046 * This function inspects the scan response buffer for pointers to
1047 * expected TLVs.
1048 *
1049 * TLVs can be included at the end of the scan response BSS information.
1050 *
1051 * Data in the buffer is parsed pointers to TLVs that can potentially
1052 * be passed back in the response.
1053 */
1054static void
1055mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1056				     struct mwifiex_ie_types_data *tlv,
1057				     u32 tlv_buf_size, u32 req_tlv_type,
1058				     struct mwifiex_ie_types_data **tlv_data)
1059{
1060	struct mwifiex_ie_types_data *current_tlv;
1061	u32 tlv_buf_left;
1062	u32 tlv_type;
1063	u32 tlv_len;
1064
1065	current_tlv = tlv;
1066	tlv_buf_left = tlv_buf_size;
1067	*tlv_data = NULL;
1068
1069	dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n",
1070		tlv_buf_size);
1071
1072	while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1073
1074		tlv_type = le16_to_cpu(current_tlv->header.type);
1075		tlv_len = le16_to_cpu(current_tlv->header.len);
1076
1077		if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1078			dev_err(adapter->dev, "SCAN_RESP: TLV buffer corrupt\n");
1079			break;
1080		}
1081
1082		if (req_tlv_type == tlv_type) {
1083			switch (tlv_type) {
1084			case TLV_TYPE_TSFTIMESTAMP:
1085				dev_dbg(adapter->dev, "info: SCAN_RESP: TSF "
1086					"timestamp TLV, len = %d\n", tlv_len);
1087				*tlv_data = current_tlv;
1088				break;
1089			case TLV_TYPE_CHANNELBANDLIST:
1090				dev_dbg(adapter->dev, "info: SCAN_RESP: channel"
1091					" band list TLV, len = %d\n", tlv_len);
1092				*tlv_data = current_tlv;
1093				break;
1094			default:
1095				dev_err(adapter->dev,
1096					"SCAN_RESP: unhandled TLV = %d\n",
1097				       tlv_type);
1098				/* Give up, this seems corrupted */
1099				return;
1100			}
1101		}
1102
1103		if (*tlv_data)
1104			break;
1105
1106
1107		tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1108		current_tlv =
1109			(struct mwifiex_ie_types_data *) (current_tlv->data +
1110							  tlv_len);
1111
1112	}			/* while */
1113}
1114
1115/*
1116 * This function parses provided beacon buffer and updates
1117 * respective fields in bss descriptor structure.
1118 */
1119int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1120				    struct mwifiex_bssdescriptor *bss_entry)
1121{
1122	int ret = 0;
1123	u8 element_id;
1124	struct ieee_types_fh_param_set *fh_param_set;
1125	struct ieee_types_ds_param_set *ds_param_set;
1126	struct ieee_types_cf_param_set *cf_param_set;
1127	struct ieee_types_ibss_param_set *ibss_param_set;
1128	u8 *current_ptr;
1129	u8 *rate;
1130	u8 element_len;
1131	u16 total_ie_len;
1132	u8 bytes_to_copy;
1133	u8 rate_size;
1134	u8 found_data_rate_ie;
1135	u32 bytes_left;
1136	struct ieee_types_vendor_specific *vendor_ie;
1137	const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1138	const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1139
1140	found_data_rate_ie = false;
1141	rate_size = 0;
1142	current_ptr = bss_entry->beacon_buf;
1143	bytes_left = bss_entry->beacon_buf_size;
1144
1145	/* Process variable IE */
1146	while (bytes_left >= 2) {
1147		element_id = *current_ptr;
1148		element_len = *(current_ptr + 1);
1149		total_ie_len = element_len + sizeof(struct ieee_types_header);
1150
1151		if (bytes_left < total_ie_len) {
1152			dev_err(adapter->dev, "err: InterpretIE: in processing"
1153				" IE, bytes left < IE length\n");
1154			return -1;
1155		}
1156		switch (element_id) {
1157		case WLAN_EID_SSID:
1158			bss_entry->ssid.ssid_len = element_len;
1159			memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1160			       element_len);
1161			dev_dbg(adapter->dev,
1162				"info: InterpretIE: ssid: %-32s\n",
1163				bss_entry->ssid.ssid);
1164			break;
1165
1166		case WLAN_EID_SUPP_RATES:
1167			memcpy(bss_entry->data_rates, current_ptr + 2,
1168			       element_len);
1169			memcpy(bss_entry->supported_rates, current_ptr + 2,
1170			       element_len);
1171			rate_size = element_len;
1172			found_data_rate_ie = true;
1173			break;
1174
1175		case WLAN_EID_FH_PARAMS:
1176			fh_param_set =
1177				(struct ieee_types_fh_param_set *) current_ptr;
1178			memcpy(&bss_entry->phy_param_set.fh_param_set,
1179			       fh_param_set,
1180			       sizeof(struct ieee_types_fh_param_set));
1181			break;
1182
1183		case WLAN_EID_DS_PARAMS:
1184			ds_param_set =
1185				(struct ieee_types_ds_param_set *) current_ptr;
1186
1187			bss_entry->channel = ds_param_set->current_chan;
1188
1189			memcpy(&bss_entry->phy_param_set.ds_param_set,
1190			       ds_param_set,
1191			       sizeof(struct ieee_types_ds_param_set));
1192			break;
1193
1194		case WLAN_EID_CF_PARAMS:
1195			cf_param_set =
1196				(struct ieee_types_cf_param_set *) current_ptr;
1197			memcpy(&bss_entry->ss_param_set.cf_param_set,
1198			       cf_param_set,
1199			       sizeof(struct ieee_types_cf_param_set));
1200			break;
1201
1202		case WLAN_EID_IBSS_PARAMS:
1203			ibss_param_set =
1204				(struct ieee_types_ibss_param_set *)
1205				current_ptr;
1206			memcpy(&bss_entry->ss_param_set.ibss_param_set,
1207			       ibss_param_set,
1208			       sizeof(struct ieee_types_ibss_param_set));
1209			break;
1210
1211		case WLAN_EID_ERP_INFO:
1212			bss_entry->erp_flags = *(current_ptr + 2);
1213			break;
1214
1215		case WLAN_EID_PWR_CONSTRAINT:
1216			bss_entry->local_constraint = *(current_ptr + 2);
1217			bss_entry->sensed_11h = true;
1218			break;
1219
1220		case WLAN_EID_CHANNEL_SWITCH:
1221			bss_entry->chan_sw_ie_present = true;
1222		case WLAN_EID_PWR_CAPABILITY:
1223		case WLAN_EID_TPC_REPORT:
1224		case WLAN_EID_QUIET:
1225			bss_entry->sensed_11h = true;
1226		    break;
1227
1228		case WLAN_EID_EXT_SUPP_RATES:
1229			/*
1230			 * Only process extended supported rate
1231			 * if data rate is already found.
1232			 * Data rate IE should come before
1233			 * extended supported rate IE
1234			 */
1235			if (found_data_rate_ie) {
1236				if ((element_len + rate_size) >
1237				    MWIFIEX_SUPPORTED_RATES)
1238					bytes_to_copy =
1239						(MWIFIEX_SUPPORTED_RATES -
1240						 rate_size);
1241				else
1242					bytes_to_copy = element_len;
1243
1244				rate = (u8 *) bss_entry->data_rates;
1245				rate += rate_size;
1246				memcpy(rate, current_ptr + 2, bytes_to_copy);
1247
1248				rate = (u8 *) bss_entry->supported_rates;
1249				rate += rate_size;
1250				memcpy(rate, current_ptr + 2, bytes_to_copy);
1251			}
1252			break;
1253
1254		case WLAN_EID_VENDOR_SPECIFIC:
1255			vendor_ie = (struct ieee_types_vendor_specific *)
1256					current_ptr;
1257
1258			if (!memcmp
1259			    (vendor_ie->vend_hdr.oui, wpa_oui,
1260			     sizeof(wpa_oui))) {
1261				bss_entry->bcn_wpa_ie =
1262					(struct ieee_types_vendor_specific *)
1263					current_ptr;
1264				bss_entry->wpa_offset = (u16)
1265					(current_ptr - bss_entry->beacon_buf);
1266			} else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
1267				    sizeof(wmm_oui))) {
1268				if (total_ie_len ==
1269				    sizeof(struct ieee_types_wmm_parameter) ||
1270				    total_ie_len ==
1271				    sizeof(struct ieee_types_wmm_info))
1272					/*
1273					 * Only accept and copy the WMM IE if
1274					 * it matches the size expected for the
1275					 * WMM Info IE or the WMM Parameter IE.
1276					 */
1277					memcpy((u8 *) &bss_entry->wmm_ie,
1278					       current_ptr, total_ie_len);
1279			}
1280			break;
1281		case WLAN_EID_RSN:
1282			bss_entry->bcn_rsn_ie =
1283				(struct ieee_types_generic *) current_ptr;
1284			bss_entry->rsn_offset = (u16) (current_ptr -
1285							bss_entry->beacon_buf);
1286			break;
1287		case WLAN_EID_BSS_AC_ACCESS_DELAY:
1288			bss_entry->bcn_wapi_ie =
1289				(struct ieee_types_generic *) current_ptr;
1290			bss_entry->wapi_offset = (u16) (current_ptr -
1291							bss_entry->beacon_buf);
1292			break;
1293		case WLAN_EID_HT_CAPABILITY:
1294			bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1295					(current_ptr +
1296					sizeof(struct ieee_types_header));
1297			bss_entry->ht_cap_offset = (u16) (current_ptr +
1298					sizeof(struct ieee_types_header) -
1299					bss_entry->beacon_buf);
1300			break;
1301		case WLAN_EID_HT_OPERATION:
1302			bss_entry->bcn_ht_oper =
1303				(struct ieee80211_ht_operation *)(current_ptr +
1304					sizeof(struct ieee_types_header));
1305			bss_entry->ht_info_offset = (u16) (current_ptr +
1306					sizeof(struct ieee_types_header) -
1307					bss_entry->beacon_buf);
1308			break;
1309		case WLAN_EID_VHT_CAPABILITY:
1310			bss_entry->disable_11ac = false;
1311			bss_entry->bcn_vht_cap =
1312				(void *)(current_ptr +
1313					 sizeof(struct ieee_types_header));
1314			bss_entry->vht_cap_offset =
1315					(u16)((u8 *)bss_entry->bcn_vht_cap -
1316					      bss_entry->beacon_buf);
1317			break;
1318		case WLAN_EID_VHT_OPERATION:
1319			bss_entry->bcn_vht_oper =
1320				(void *)(current_ptr +
1321					 sizeof(struct ieee_types_header));
1322			bss_entry->vht_info_offset =
1323					(u16)((u8 *)bss_entry->bcn_vht_oper -
1324					      bss_entry->beacon_buf);
1325			break;
1326		case WLAN_EID_BSS_COEX_2040:
1327			bss_entry->bcn_bss_co_2040 = current_ptr +
1328				sizeof(struct ieee_types_header);
1329			bss_entry->bss_co_2040_offset = (u16) (current_ptr +
1330					sizeof(struct ieee_types_header) -
1331						bss_entry->beacon_buf);
1332			break;
1333		case WLAN_EID_EXT_CAPABILITY:
1334			bss_entry->bcn_ext_cap = current_ptr +
1335				sizeof(struct ieee_types_header);
1336			bss_entry->ext_cap_offset = (u16) (current_ptr +
1337					sizeof(struct ieee_types_header) -
1338					bss_entry->beacon_buf);
1339			break;
1340		case WLAN_EID_OPMODE_NOTIF:
1341			bss_entry->oper_mode =
1342				(void *)(current_ptr +
1343					 sizeof(struct ieee_types_header));
1344			bss_entry->oper_mode_offset =
1345					(u16)((u8 *)bss_entry->oper_mode -
1346					      bss_entry->beacon_buf);
1347			break;
1348		default:
1349			break;
1350		}
1351
1352		current_ptr += element_len + 2;
1353
1354		/* Need to account for IE ID and IE Len */
1355		bytes_left -= (element_len + 2);
1356
1357	}	/* while (bytes_left > 2) */
1358	return ret;
1359}
1360
1361/*
1362 * This function converts radio type scan parameter to a band configuration
1363 * to be used in join command.
1364 */
1365static u8
1366mwifiex_radio_type_to_band(u8 radio_type)
1367{
1368	switch (radio_type) {
1369	case HostCmd_SCAN_RADIO_TYPE_A:
1370		return BAND_A;
1371	case HostCmd_SCAN_RADIO_TYPE_BG:
1372	default:
1373		return BAND_G;
1374	}
1375}
1376
1377/*
1378 * This is an internal function used to start a scan based on an input
1379 * configuration.
1380 *
1381 * This uses the input user scan configuration information when provided in
1382 * order to send the appropriate scan commands to firmware to populate or
1383 * update the internal driver scan table.
1384 */
1385int mwifiex_scan_networks(struct mwifiex_private *priv,
1386			  const struct mwifiex_user_scan_cfg *user_scan_in)
1387{
1388	int ret;
1389	struct mwifiex_adapter *adapter = priv->adapter;
1390	struct cmd_ctrl_node *cmd_node;
1391	union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1392	struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1393	struct mwifiex_chan_scan_param_set *scan_chan_list;
1394	u8 filtered_scan;
1395	u8 scan_current_chan_only;
1396	u8 max_chan_per_scan;
1397	unsigned long flags;
1398
1399	if (adapter->scan_processing) {
1400		dev_err(adapter->dev, "cmd: Scan already in process...\n");
1401		return -EBUSY;
1402	}
1403
1404	if (priv->scan_block) {
1405		dev_err(adapter->dev,
1406			"cmd: Scan is blocked during association...\n");
1407		return -EBUSY;
1408	}
1409
1410	spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1411	adapter->scan_processing = true;
1412	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1413
1414	scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1415			       GFP_KERNEL);
1416	if (!scan_cfg_out) {
1417		ret = -ENOMEM;
1418		goto done;
1419	}
1420
1421	scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1422				 sizeof(struct mwifiex_chan_scan_param_set),
1423				 GFP_KERNEL);
1424	if (!scan_chan_list) {
1425		kfree(scan_cfg_out);
1426		ret = -ENOMEM;
1427		goto done;
1428	}
1429
1430	mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1431			    &chan_list_out, scan_chan_list, &max_chan_per_scan,
1432			    &filtered_scan, &scan_current_chan_only);
1433
1434	ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1435					&scan_cfg_out->config, chan_list_out,
1436					scan_chan_list);
1437
1438	/* Get scan command from scan_pending_q and put to cmd_pending_q */
1439	if (!ret) {
1440		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1441		if (!list_empty(&adapter->scan_pending_q)) {
1442			cmd_node = list_first_entry(&adapter->scan_pending_q,
1443						    struct cmd_ctrl_node, list);
1444			list_del(&cmd_node->list);
1445			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1446					       flags);
1447			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
1448							true);
1449			queue_work(adapter->workqueue, &adapter->main_work);
1450
1451			/* Perform internal scan synchronously */
1452			if (!priv->scan_request) {
1453				dev_dbg(adapter->dev, "wait internal scan\n");
1454				mwifiex_wait_queue_complete(adapter, cmd_node);
1455			}
1456		} else {
1457			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1458					       flags);
1459		}
1460	}
1461
1462	kfree(scan_cfg_out);
1463	kfree(scan_chan_list);
1464done:
1465	if (ret) {
1466		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1467		adapter->scan_processing = false;
1468		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1469	}
1470	return ret;
1471}
1472
1473/*
1474 * This function prepares a scan command to be sent to the firmware.
1475 *
1476 * This uses the scan command configuration sent to the command processing
1477 * module in command preparation stage to configure a scan command structure
1478 * to send to firmware.
1479 *
1480 * The fixed fields specifying the BSS type and BSSID filters as well as a
1481 * variable number/length of TLVs are sent in the command to firmware.
1482 *
1483 * Preparation also includes -
1484 *      - Setting command ID, and proper size
1485 *      - Ensuring correct endian-ness
1486 */
1487int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1488			    struct mwifiex_scan_cmd_config *scan_cfg)
1489{
1490	struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1491
1492	/* Set fixed field variables in scan command */
1493	scan_cmd->bss_mode = scan_cfg->bss_mode;
1494	memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1495	       sizeof(scan_cmd->bssid));
1496	memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1497
1498	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1499
1500	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1501	cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1502					  + sizeof(scan_cmd->bssid)
1503					  + scan_cfg->tlv_buf_len + S_DS_GEN));
1504
1505	return 0;
1506}
1507
1508/*
1509 * This function checks compatibility of requested network with current
1510 * driver settings.
1511 */
1512int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1513					struct mwifiex_bssdescriptor *bss_desc)
1514{
1515	int ret = -1;
1516
1517	if (!bss_desc)
1518		return -1;
1519
1520	if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1521			     (u16) bss_desc->channel, 0))) {
1522		switch (priv->bss_mode) {
1523		case NL80211_IFTYPE_STATION:
1524		case NL80211_IFTYPE_ADHOC:
1525			ret = mwifiex_is_network_compatible(priv, bss_desc,
1526							    priv->bss_mode);
1527			if (ret)
1528				dev_err(priv->adapter->dev,
1529					"Incompatible network settings\n");
1530			break;
1531		default:
1532			ret = 0;
1533		}
1534	}
1535
1536	return ret;
1537}
1538
1539static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1540					  struct cfg80211_bss *bss)
1541{
1542	struct mwifiex_bssdescriptor *bss_desc;
1543	int ret;
1544	unsigned long flags;
1545
1546	/* Allocate and fill new bss descriptor */
1547	bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1548	if (!bss_desc)
1549		return -ENOMEM;
1550
1551	ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1552	if (ret)
1553		goto done;
1554
1555	ret = mwifiex_check_network_compatibility(priv, bss_desc);
1556	if (ret)
1557		goto done;
1558
1559	spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1560	/* Make a copy of current BSSID descriptor */
1561	memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1562	       sizeof(priv->curr_bss_params.bss_descriptor));
1563
1564	/* The contents of beacon_ie will be copied to its own buffer
1565	 * in mwifiex_save_curr_bcn()
1566	 */
1567	mwifiex_save_curr_bcn(priv);
1568	spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1569
1570done:
1571	/* beacon_ie buffer was allocated in function
1572	 * mwifiex_fill_new_bss_desc(). Free it now.
1573	 */
1574	kfree(bss_desc->beacon_buf);
1575	kfree(bss_desc);
1576	return 0;
1577}
1578
1579/*
1580 * This function handles the command response of scan.
1581 *
1582 * The response buffer for the scan command has the following
1583 * memory layout:
1584 *
1585 *      .-------------------------------------------------------------.
1586 *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
1587 *      .-------------------------------------------------------------.
1588 *      |  BufSize (t_u16) : sizeof the BSS Description data          |
1589 *      .-------------------------------------------------------------.
1590 *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
1591 *      .-------------------------------------------------------------.
1592 *      |  BSSDescription data (variable, size given in BufSize)      |
1593 *      .-------------------------------------------------------------.
1594 *      |  TLV data (variable, size calculated using Header->Size,    |
1595 *      |            BufSize and sizeof the fixed fields above)       |
1596 *      .-------------------------------------------------------------.
1597 */
1598int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1599			    struct host_cmd_ds_command *resp)
1600{
1601	int ret = 0;
1602	struct mwifiex_adapter *adapter = priv->adapter;
1603	struct cmd_ctrl_node *cmd_node;
1604	struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
1605	struct mwifiex_ie_types_data *tlv_data;
1606	struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
1607	u8 *bss_info;
1608	u32 scan_resp_size;
1609	u32 bytes_left;
1610	u32 idx;
1611	u32 tlv_buf_size;
1612	struct mwifiex_chan_freq_power *cfp;
1613	struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
1614	struct chan_band_param_set *chan_band;
1615	u8 is_bgscan_resp;
1616	unsigned long flags;
1617	struct cfg80211_bss *bss;
1618
1619	is_bgscan_resp = (le16_to_cpu(resp->command)
1620			  == HostCmd_CMD_802_11_BG_SCAN_QUERY);
1621	if (is_bgscan_resp)
1622		scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
1623	else
1624		scan_rsp = &resp->params.scan_resp;
1625
1626
1627	if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
1628		dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
1629			scan_rsp->number_of_sets);
1630		ret = -1;
1631		goto check_next_scan;
1632	}
1633
1634	/* Check csa channel expiry before parsing scan response */
1635	mwifiex_11h_get_csa_closed_channel(priv);
1636
1637	bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
1638	dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n",
1639		bytes_left);
1640
1641	scan_resp_size = le16_to_cpu(resp->size);
1642
1643	dev_dbg(adapter->dev,
1644		"info: SCAN_RESP: returned %d APs before parsing\n",
1645		scan_rsp->number_of_sets);
1646
1647	bss_info = scan_rsp->bss_desc_and_tlv_buffer;
1648
1649	/*
1650	 * The size of the TLV buffer is equal to the entire command response
1651	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
1652	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
1653	 *   response header (S_DS_GEN)
1654	 */
1655	tlv_buf_size = scan_resp_size - (bytes_left
1656					 + sizeof(scan_rsp->bss_descript_size)
1657					 + sizeof(scan_rsp->number_of_sets)
1658					 + S_DS_GEN);
1659
1660	tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
1661						 bss_desc_and_tlv_buffer +
1662						 bytes_left);
1663
1664	/* Search the TLV buffer space in the scan response for any valid
1665	   TLVs */
1666	mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
1667					     TLV_TYPE_TSFTIMESTAMP,
1668					     (struct mwifiex_ie_types_data **)
1669					     &tsf_tlv);
1670
1671	/* Search the TLV buffer space in the scan response for any valid
1672	   TLVs */
1673	mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
1674					     TLV_TYPE_CHANNELBANDLIST,
1675					     (struct mwifiex_ie_types_data **)
1676					     &chan_band_tlv);
1677
1678	for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
1679		u8 bssid[ETH_ALEN];
1680		s32 rssi;
1681		const u8 *ie_buf;
1682		size_t ie_len;
1683		u16 channel = 0;
1684		u64 fw_tsf = 0;
1685		u16 beacon_size = 0;
1686		u32 curr_bcn_bytes;
1687		u32 freq;
1688		u16 beacon_period;
1689		u16 cap_info_bitmap;
1690		u8 *current_ptr;
1691		u64 timestamp;
1692		struct mwifiex_bcn_param *bcn_param;
1693		struct mwifiex_bss_priv *bss_priv;
1694
1695		if (bytes_left >= sizeof(beacon_size)) {
1696			/* Extract & convert beacon size from command buffer */
1697			memcpy(&beacon_size, bss_info, sizeof(beacon_size));
1698			bytes_left -= sizeof(beacon_size);
1699			bss_info += sizeof(beacon_size);
1700		}
1701
1702		if (!beacon_size || beacon_size > bytes_left) {
1703			bss_info += bytes_left;
1704			bytes_left = 0;
1705			ret = -1;
1706			goto check_next_scan;
1707		}
1708
1709		/* Initialize the current working beacon pointer for this BSS
1710		 * iteration */
1711		current_ptr = bss_info;
1712
1713		/* Advance the return beacon pointer past the current beacon */
1714		bss_info += beacon_size;
1715		bytes_left -= beacon_size;
1716
1717		curr_bcn_bytes = beacon_size;
1718
1719		/*
1720		 * First 5 fields are bssid, RSSI, time stamp, beacon interval,
1721		 *   and capability information
1722		 */
1723		if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
1724			dev_err(adapter->dev,
1725				"InterpretIE: not enough bytes left\n");
1726			continue;
1727		}
1728		bcn_param = (struct mwifiex_bcn_param *)current_ptr;
1729		current_ptr += sizeof(*bcn_param);
1730		curr_bcn_bytes -= sizeof(*bcn_param);
1731
1732		memcpy(bssid, bcn_param->bssid, ETH_ALEN);
1733
1734		rssi = (s32) bcn_param->rssi;
1735		rssi = (-rssi) * 100;		/* Convert dBm to mBm */
1736		dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
1737
1738		timestamp = le64_to_cpu(bcn_param->timestamp);
1739		beacon_period = le16_to_cpu(bcn_param->beacon_period);
1740
1741		cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1742		dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1743			cap_info_bitmap);
1744
1745		/* Rest of the current buffer are IE's */
1746		ie_buf = current_ptr;
1747		ie_len = curr_bcn_bytes;
1748		dev_dbg(adapter->dev,
1749			"info: InterpretIE: IELength for this AP = %d\n",
1750			curr_bcn_bytes);
1751
1752		while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1753			u8 element_id, element_len;
1754
1755			element_id = *current_ptr;
1756			element_len = *(current_ptr + 1);
1757			if (curr_bcn_bytes < element_len +
1758					sizeof(struct ieee_types_header)) {
1759				dev_err(priv->adapter->dev,
1760					"%s: bytes left < IE length\n",
1761					__func__);
1762				goto check_next_scan;
1763			}
1764			if (element_id == WLAN_EID_DS_PARAMS) {
1765				channel = *(current_ptr + sizeof(struct ieee_types_header));
1766				break;
1767			}
1768
1769			current_ptr += element_len +
1770					sizeof(struct ieee_types_header);
1771			curr_bcn_bytes -= element_len +
1772					sizeof(struct ieee_types_header);
1773		}
1774
1775		/*
1776		 * If the TSF TLV was appended to the scan results, save this
1777		 * entry's TSF value in the fw_tsf field. It is the firmware's
1778		 * TSF value at the time the beacon or probe response was
1779		 * received.
1780		 */
1781		if (tsf_tlv)
1782			memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
1783			       sizeof(fw_tsf));
1784
1785		if (channel) {
1786			struct ieee80211_channel *chan;
1787			u8 band;
1788
1789			/* Skip entry if on csa closed channel */
1790			if (channel == priv->csa_chan) {
1791				dev_dbg(adapter->dev,
1792					"Dropping entry on csa closed channel\n");
1793				continue;
1794			}
1795
1796			band = BAND_G;
1797			if (chan_band_tlv) {
1798				chan_band =
1799					&chan_band_tlv->chan_band_param[idx];
1800				band = mwifiex_radio_type_to_band(
1801						chan_band->radio_type
1802						& (BIT(0) | BIT(1)));
1803			}
1804
1805			cfp = mwifiex_get_cfp(priv, band, channel, 0);
1806
1807			freq = cfp ? cfp->freq : 0;
1808
1809			chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
1810
1811			if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1812				bss = cfg80211_inform_bss(priv->wdev->wiphy,
1813					      chan, bssid, timestamp,
1814					      cap_info_bitmap, beacon_period,
1815					      ie_buf, ie_len, rssi, GFP_KERNEL);
1816				bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1817				bss_priv->band = band;
1818				bss_priv->fw_tsf = fw_tsf;
1819				if (priv->media_connected &&
1820				    !memcmp(bssid,
1821					    priv->curr_bss_params.bss_descriptor
1822					    .mac_address, ETH_ALEN))
1823					mwifiex_update_curr_bss_params(priv,
1824								       bss);
1825				cfg80211_put_bss(priv->wdev->wiphy, bss);
1826			}
1827		} else {
1828			dev_dbg(adapter->dev, "missing BSS channel IE\n");
1829		}
1830	}
1831
1832check_next_scan:
1833	spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1834	if (list_empty(&adapter->scan_pending_q)) {
1835		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
1836		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1837		adapter->scan_processing = false;
1838		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1839
1840		/* Need to indicate IOCTL complete */
1841		if (adapter->curr_cmd->wait_q_enabled) {
1842			adapter->cmd_wait_q.status = 0;
1843			if (!priv->scan_request) {
1844				dev_dbg(adapter->dev,
1845					"complete internal scan\n");
1846				mwifiex_complete_cmd(adapter,
1847						     adapter->curr_cmd);
1848			}
1849		}
1850		if (priv->report_scan_result)
1851			priv->report_scan_result = false;
1852
1853		if (priv->scan_request) {
1854			dev_dbg(adapter->dev, "info: notifying scan done\n");
1855			cfg80211_scan_done(priv->scan_request, 0);
1856			priv->scan_request = NULL;
1857		} else {
1858			priv->scan_aborting = false;
1859			dev_dbg(adapter->dev, "info: scan already aborted\n");
1860		}
1861	} else {
1862		if ((priv->scan_aborting && !priv->scan_request) ||
1863		    priv->scan_block) {
1864			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1865					       flags);
1866			adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
1867			mod_timer(&priv->scan_delay_timer, jiffies);
1868			dev_dbg(priv->adapter->dev,
1869				"info: %s: triggerring scan abort\n", __func__);
1870		} else if (!mwifiex_wmm_lists_empty(adapter) &&
1871			   (priv->scan_request && (priv->scan_request->flags &
1872					    NL80211_SCAN_FLAG_LOW_PRIORITY))) {
1873			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1874					       flags);
1875			adapter->scan_delay_cnt = 1;
1876			mod_timer(&priv->scan_delay_timer, jiffies +
1877				  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
1878			dev_dbg(priv->adapter->dev,
1879				"info: %s: deferring scan\n", __func__);
1880		} else {
1881			/* Get scan command from scan_pending_q and put to
1882			   cmd_pending_q */
1883			cmd_node = list_first_entry(&adapter->scan_pending_q,
1884						    struct cmd_ctrl_node, list);
1885			list_del(&cmd_node->list);
1886			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1887					       flags);
1888			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
1889							true);
1890		}
1891	}
1892
1893	return ret;
1894}
1895
1896/*
1897 * This function prepares command for background scan query.
1898 *
1899 * Preparation includes -
1900 *      - Setting command ID and proper size
1901 *      - Setting background scan flush parameter
1902 *      - Ensuring correct endian-ness
1903 */
1904int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
1905{
1906	struct host_cmd_ds_802_11_bg_scan_query *bg_query =
1907		&cmd->params.bg_scan_query;
1908
1909	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
1910	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
1911				+ S_DS_GEN);
1912
1913	bg_query->flush = 1;
1914
1915	return 0;
1916}
1917
1918/*
1919 * This function inserts scan command node to the scan pending queue.
1920 */
1921void
1922mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
1923		       struct cmd_ctrl_node *cmd_node)
1924{
1925	struct mwifiex_adapter *adapter = priv->adapter;
1926	unsigned long flags;
1927
1928	cmd_node->wait_q_enabled = true;
1929	cmd_node->condition = &adapter->scan_wait_q_woken;
1930	spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1931	list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
1932	spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
1933}
1934
1935/*
1936 * This function sends a scan command for all available channels to the
1937 * firmware, filtered on a specific SSID.
1938 */
1939static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
1940				      struct cfg80211_ssid *req_ssid)
1941{
1942	struct mwifiex_adapter *adapter = priv->adapter;
1943	int ret;
1944	struct mwifiex_user_scan_cfg *scan_cfg;
1945
1946	if (adapter->scan_processing) {
1947		dev_err(adapter->dev, "cmd: Scan already in process...\n");
1948		return -EBUSY;
1949	}
1950
1951	if (priv->scan_block) {
1952		dev_err(adapter->dev,
1953			"cmd: Scan is blocked during association...\n");
1954		return -EBUSY;
1955	}
1956
1957	scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
1958	if (!scan_cfg)
1959		return -ENOMEM;
1960
1961	scan_cfg->ssid_list = req_ssid;
1962	scan_cfg->num_ssids = 1;
1963
1964	ret = mwifiex_scan_networks(priv, scan_cfg);
1965
1966	kfree(scan_cfg);
1967	return ret;
1968}
1969
1970/*
1971 * Sends IOCTL request to start a scan.
1972 *
1973 * This function allocates the IOCTL request buffer, fills it
1974 * with requisite parameters and calls the IOCTL handler.
1975 *
1976 * Scan command can be issued for both normal scan and specific SSID
1977 * scan, depending upon whether an SSID is provided or not.
1978 */
1979int mwifiex_request_scan(struct mwifiex_private *priv,
1980			 struct cfg80211_ssid *req_ssid)
1981{
1982	int ret;
1983
1984	if (down_interruptible(&priv->async_sem)) {
1985		dev_err(priv->adapter->dev, "%s: acquire semaphore\n",
1986			__func__);
1987		return -1;
1988	}
1989
1990	priv->adapter->scan_wait_q_woken = false;
1991
1992	if (req_ssid && req_ssid->ssid_len != 0)
1993		/* Specific SSID scan */
1994		ret = mwifiex_scan_specific_ssid(priv, req_ssid);
1995	else
1996		/* Normal scan */
1997		ret = mwifiex_scan_networks(priv, NULL);
1998
1999	up(&priv->async_sem);
2000
2001	return ret;
2002}
2003
2004/*
2005 * This function appends the vendor specific IE TLV to a buffer.
2006 */
2007int
2008mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2009			    u16 vsie_mask, u8 **buffer)
2010{
2011	int id, ret_len = 0;
2012	struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2013
2014	if (!buffer)
2015		return 0;
2016	if (!(*buffer))
2017		return 0;
2018
2019	/*
2020	 * Traverse through the saved vendor specific IE array and append
2021	 * the selected(scan/assoc/adhoc) IE as TLV to the command
2022	 */
2023	for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2024		if (priv->vs_ie[id].mask & vsie_mask) {
2025			vs_param_set =
2026				(struct mwifiex_ie_types_vendor_param_set *)
2027				*buffer;
2028			vs_param_set->header.type =
2029				cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2030			vs_param_set->header.len =
2031				cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2032				& 0x00FF) + 2);
2033			memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2034			       le16_to_cpu(vs_param_set->header.len));
2035			*buffer += le16_to_cpu(vs_param_set->header.len) +
2036				   sizeof(struct mwifiex_ie_types_header);
2037			ret_len += le16_to_cpu(vs_param_set->header.len) +
2038				   sizeof(struct mwifiex_ie_types_header);
2039		}
2040	}
2041	return ret_len;
2042}
2043
2044/*
2045 * This function saves a beacon buffer of the current BSS descriptor.
2046 *
2047 * The current beacon buffer is saved so that it can be restored in the
2048 * following cases that makes the beacon buffer not to contain the current
2049 * ssid's beacon buffer.
2050 *      - The current ssid was not found somehow in the last scan.
2051 *      - The current ssid was the last entry of the scan table and overloaded.
2052 */
2053void
2054mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2055{
2056	struct mwifiex_bssdescriptor *curr_bss =
2057		&priv->curr_bss_params.bss_descriptor;
2058
2059	if (!curr_bss->beacon_buf_size)
2060		return;
2061
2062	/* allocate beacon buffer at 1st time; or if it's size has changed */
2063	if (!priv->curr_bcn_buf ||
2064	    priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2065		priv->curr_bcn_size = curr_bss->beacon_buf_size;
2066
2067		kfree(priv->curr_bcn_buf);
2068		priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2069					     GFP_ATOMIC);
2070		if (!priv->curr_bcn_buf)
2071			return;
2072	}
2073
2074	memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2075	       curr_bss->beacon_buf_size);
2076	dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
2077		priv->curr_bcn_size);
2078
2079	curr_bss->beacon_buf = priv->curr_bcn_buf;
2080
2081	/* adjust the pointers in the current BSS descriptor */
2082	if (curr_bss->bcn_wpa_ie)
2083		curr_bss->bcn_wpa_ie =
2084			(struct ieee_types_vendor_specific *)
2085			(curr_bss->beacon_buf +
2086			 curr_bss->wpa_offset);
2087
2088	if (curr_bss->bcn_rsn_ie)
2089		curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2090			(curr_bss->beacon_buf +
2091			 curr_bss->rsn_offset);
2092
2093	if (curr_bss->bcn_ht_cap)
2094		curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2095			(curr_bss->beacon_buf +
2096			 curr_bss->ht_cap_offset);
2097
2098	if (curr_bss->bcn_ht_oper)
2099		curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2100			(curr_bss->beacon_buf +
2101			 curr_bss->ht_info_offset);
2102
2103	if (curr_bss->bcn_vht_cap)
2104		curr_bss->bcn_ht_cap = (void *)(curr_bss->beacon_buf +
2105						curr_bss->vht_cap_offset);
2106
2107	if (curr_bss->bcn_vht_oper)
2108		curr_bss->bcn_ht_oper = (void *)(curr_bss->beacon_buf +
2109						 curr_bss->vht_info_offset);
2110
2111	if (curr_bss->bcn_bss_co_2040)
2112		curr_bss->bcn_bss_co_2040 =
2113			(curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2114
2115	if (curr_bss->bcn_ext_cap)
2116		curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2117			curr_bss->ext_cap_offset;
2118
2119	if (curr_bss->oper_mode)
2120		curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2121					       curr_bss->oper_mode_offset);
2122}
2123
2124/*
2125 * This function frees the current BSS descriptor beacon buffer.
2126 */
2127void
2128mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2129{
2130	kfree(priv->curr_bcn_buf);
2131	priv->curr_bcn_buf = NULL;
2132}