Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1/*
   2 * Marvell Wireless LAN device driver: scan ioctl and command handling
   3 *
   4 * Copyright (C) 2011-2014, 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
  33/* Memory needed to store a max sized Channel List TLV for a firmware scan */
  34#define CHAN_TLV_MAX_SIZE  (sizeof(struct mwifiex_ie_types_header)         \
  35				+ (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN     \
  36				*sizeof(struct mwifiex_chan_scan_param_set)))
  37
  38/* Memory needed to store supported rate */
  39#define RATE_TLV_MAX_SIZE   (sizeof(struct mwifiex_ie_types_rates_param_set) \
  40				+ HOSTCMD_SUPPORTED_RATES)
  41
  42/* Memory needed to store a max number/size WildCard SSID TLV for a firmware
  43	scan */
  44#define WILDCARD_SSID_TLV_MAX_SIZE  \
  45	(MWIFIEX_MAX_SSID_LIST_LENGTH *					\
  46		(sizeof(struct mwifiex_ie_types_wildcard_ssid_params)	\
  47			+ IEEE80211_MAX_SSID_LEN))
  48
  49/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
  50#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config)        \
  51				+ sizeof(struct mwifiex_ie_types_num_probes)   \
  52				+ sizeof(struct mwifiex_ie_types_htcap)       \
  53				+ CHAN_TLV_MAX_SIZE                 \
  54				+ RATE_TLV_MAX_SIZE                 \
  55				+ WILDCARD_SSID_TLV_MAX_SIZE)
  56
  57
  58union mwifiex_scan_cmd_config_tlv {
  59	/* Scan configuration (variable length) */
  60	struct mwifiex_scan_cmd_config config;
  61	/* Max allocated block */
  62	u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
  63};
  64
  65enum cipher_suite {
  66	CIPHER_SUITE_TKIP,
  67	CIPHER_SUITE_CCMP,
  68	CIPHER_SUITE_MAX
  69};
  70static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
  71	{ 0x00, 0x50, 0xf2, 0x02 },	/* TKIP */
  72	{ 0x00, 0x50, 0xf2, 0x04 },	/* AES  */
  73};
  74static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
  75	{ 0x00, 0x0f, 0xac, 0x02 },	/* TKIP */
  76	{ 0x00, 0x0f, 0xac, 0x04 },	/* AES  */
  77};
  78
  79static void
  80_dbg_security_flags(int log_level, const char *func, const char *desc,
  81		    struct mwifiex_private *priv,
  82		    struct mwifiex_bssdescriptor *bss_desc)
  83{
  84	_mwifiex_dbg(priv->adapter, log_level,
  85		     "info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n",
  86		     func, desc,
  87		     bss_desc->bcn_wpa_ie ?
  88		     bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0,
  89		     bss_desc->bcn_rsn_ie ?
  90		     bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0,
  91		     priv->sec_info.wep_enabled ? "e" : "d",
  92		     priv->sec_info.wpa_enabled ? "e" : "d",
  93		     priv->sec_info.wpa2_enabled ? "e" : "d",
  94		     priv->sec_info.encryption_mode,
  95		     bss_desc->privacy);
  96}
  97#define dbg_security_flags(mask, desc, priv, bss_desc) \
  98	_dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc)
  99
 100static bool
 101has_ieee_hdr(struct ieee_types_generic *ie, u8 key)
 102{
 103	return (ie && ie->ieee_hdr.element_id == key);
 104}
 105
 106static bool
 107has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key)
 108{
 109	return (ie && ie->vend_hdr.element_id == key);
 110}
 111
 112/*
 113 * This function parses a given IE for a given OUI.
 114 *
 115 * This is used to parse a WPA/RSN IE to find if it has
 116 * a given oui in PTK.
 117 */
 118static u8
 119mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
 120{
 121	u8 count;
 122
 123	count = iebody->ptk_cnt[0];
 124
 125	/* There could be multiple OUIs for PTK hence
 126	   1) Take the length.
 127	   2) Check all the OUIs for AES.
 128	   3) If one of them is AES then pass success. */
 129	while (count) {
 130		if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
 131			return MWIFIEX_OUI_PRESENT;
 132
 133		--count;
 134		if (count)
 135			iebody = (struct ie_body *) ((u8 *) iebody +
 136						sizeof(iebody->ptk_body));
 137	}
 138
 139	pr_debug("info: %s: OUI is not found in PTK\n", __func__);
 140	return MWIFIEX_OUI_NOT_PRESENT;
 141}
 142
 143/*
 144 * This function checks if a given OUI is present in a RSN IE.
 145 *
 146 * The function first checks if a RSN IE is present or not in the
 147 * BSS descriptor. It tries to locate the OUI only if such an IE is
 148 * present.
 149 */
 150static u8
 151mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
 152{
 153	u8 *oui;
 154	struct ie_body *iebody;
 155	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 156
 157	if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
 158		iebody = (struct ie_body *)
 159			 (((u8 *) bss_desc->bcn_rsn_ie->data) +
 160			  RSN_GTK_OUI_OFFSET);
 161		oui = &mwifiex_rsn_oui[cipher][0];
 162		ret = mwifiex_search_oui_in_ie(iebody, oui);
 163		if (ret)
 164			return ret;
 165	}
 166	return ret;
 167}
 168
 169/*
 170 * This function checks if a given OUI is present in a WPA IE.
 171 *
 172 * The function first checks if a WPA IE is present or not in the
 173 * BSS descriptor. It tries to locate the OUI only if such an IE is
 174 * present.
 175 */
 176static u8
 177mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
 178{
 179	u8 *oui;
 180	struct ie_body *iebody;
 181	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 182
 183	if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
 184		iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
 185					    WPA_GTK_OUI_OFFSET);
 186		oui = &mwifiex_wpa_oui[cipher][0];
 187		ret = mwifiex_search_oui_in_ie(iebody, oui);
 188		if (ret)
 189			return ret;
 190	}
 191	return ret;
 192}
 193
 194/*
 195 * This function compares two SSIDs and checks if they match.
 196 */
 197s32
 198mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
 199{
 200	if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
 201		return -1;
 202	return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
 203}
 204
 205/*
 206 * This function checks if wapi is enabled in driver and scanned network is
 207 * compatible with it.
 208 */
 209static bool
 210mwifiex_is_bss_wapi(struct mwifiex_private *priv,
 211		    struct mwifiex_bssdescriptor *bss_desc)
 212{
 213	if (priv->sec_info.wapi_enabled &&
 214	    has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY))
 215		return true;
 216	return false;
 217}
 218
 219/*
 220 * This function checks if driver is configured with no security mode and
 221 * scanned network is compatible with it.
 222 */
 223static bool
 224mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
 225		      struct mwifiex_bssdescriptor *bss_desc)
 226{
 227	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 228	    !priv->sec_info.wpa2_enabled &&
 229	    !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
 230	    !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
 231	    !priv->sec_info.encryption_mode && !bss_desc->privacy) {
 232		return true;
 233	}
 234	return false;
 235}
 236
 237/*
 238 * This function checks if static WEP is enabled in driver and scanned network
 239 * is compatible with it.
 240 */
 241static bool
 242mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
 243			  struct mwifiex_bssdescriptor *bss_desc)
 244{
 245	if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 246	    !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
 247		return true;
 248	}
 249	return false;
 250}
 251
 252/*
 253 * This function checks if wpa is enabled in driver and scanned network is
 254 * compatible with it.
 255 */
 256static bool
 257mwifiex_is_bss_wpa(struct mwifiex_private *priv,
 258		   struct mwifiex_bssdescriptor *bss_desc)
 259{
 260	if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
 261	    !priv->sec_info.wpa2_enabled &&
 262	    has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)
 263	   /*
 264	    * Privacy bit may NOT be set in some APs like
 265	    * LinkSys WRT54G && bss_desc->privacy
 266	    */
 267	 ) {
 268		dbg_security_flags(INFO, "WPA", priv, bss_desc);
 269		return true;
 270	}
 271	return false;
 272}
 273
 274/*
 275 * This function checks if wpa2 is enabled in driver and scanned network is
 276 * compatible with it.
 277 */
 278static bool
 279mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
 280		    struct mwifiex_bssdescriptor *bss_desc)
 281{
 282	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 283	    priv->sec_info.wpa2_enabled &&
 284	    has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
 285		/*
 286		 * Privacy bit may NOT be set in some APs like
 287		 * LinkSys WRT54G && bss_desc->privacy
 288		 */
 289		dbg_security_flags(INFO, "WAP2", priv, bss_desc);
 290		return true;
 291	}
 292	return false;
 293}
 294
 295/*
 296 * This function checks if adhoc AES is enabled in driver and scanned network is
 297 * compatible with it.
 298 */
 299static bool
 300mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
 301			 struct mwifiex_bssdescriptor *bss_desc)
 302{
 303	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 304	    !priv->sec_info.wpa2_enabled &&
 305	    !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
 306	    !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
 307	    !priv->sec_info.encryption_mode && bss_desc->privacy) {
 308		return true;
 309	}
 310	return false;
 311}
 312
 313/*
 314 * This function checks if dynamic WEP is enabled in driver and scanned network
 315 * is compatible with it.
 316 */
 317static bool
 318mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
 319			   struct mwifiex_bssdescriptor *bss_desc)
 320{
 321	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 322	    !priv->sec_info.wpa2_enabled &&
 323	    !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
 324	    !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
 325	    priv->sec_info.encryption_mode && bss_desc->privacy) {
 326		dbg_security_flags(INFO, "dynamic", priv, bss_desc);
 327		return true;
 328	}
 329	return false;
 330}
 331
 332/*
 333 * This function checks if a scanned network is compatible with the driver
 334 * settings.
 335 *
 336 *   WEP     WPA    WPA2   ad-hoc encrypt                  Network
 337 * enabled enabled enabled  AES    mode   Privacy WPA WPA2 Compatible
 338 *    0       0       0      0     NONE      0     0   0   yes No security
 339 *    0       1       0      0      x        1x    1   x   yes WPA (disable
 340 *                                                         HT if no AES)
 341 *    0       0       1      0      x        1x    x   1   yes WPA2 (disable
 342 *                                                         HT if no AES)
 343 *    0       0       0      1     NONE      1     0   0   yes Ad-hoc AES
 344 *    1       0       0      0     NONE      1     0   0   yes Static WEP
 345 *                                                         (disable HT)
 346 *    0       0       0      0    !=NONE     1     0   0   yes Dynamic WEP
 347 *
 348 * Compatibility is not matched while roaming, except for mode.
 349 */
 350static s32
 351mwifiex_is_network_compatible(struct mwifiex_private *priv,
 352			      struct mwifiex_bssdescriptor *bss_desc, u32 mode)
 353{
 354	struct mwifiex_adapter *adapter = priv->adapter;
 355
 356	bss_desc->disable_11n = false;
 357
 358	/* Don't check for compatibility if roaming */
 359	if (priv->media_connected &&
 360	    (priv->bss_mode == NL80211_IFTYPE_STATION) &&
 361	    (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
 362		return 0;
 363
 364	if (priv->wps.session_enable) {
 365		mwifiex_dbg(adapter, IOCTL,
 366			    "info: return success directly in WPS period\n");
 367		return 0;
 368	}
 369
 370	if (bss_desc->chan_sw_ie_present) {
 371		mwifiex_dbg(adapter, INFO,
 372			    "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
 373		return -1;
 374	}
 375
 376	if (mwifiex_is_bss_wapi(priv, bss_desc)) {
 377		mwifiex_dbg(adapter, INFO,
 378			    "info: return success for WAPI AP\n");
 379		return 0;
 380	}
 381
 382	if (bss_desc->bss_mode == mode) {
 383		if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
 384			/* No security */
 385			return 0;
 386		} else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
 387			/* Static WEP enabled */
 388			mwifiex_dbg(adapter, INFO,
 389				    "info: Disable 11n in WEP mode.\n");
 390			bss_desc->disable_11n = true;
 391			return 0;
 392		} else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
 393			/* WPA enabled */
 394			if (((priv->adapter->config_bands & BAND_GN ||
 395			      priv->adapter->config_bands & BAND_AN) &&
 396			     bss_desc->bcn_ht_cap) &&
 397			    !mwifiex_is_wpa_oui_present(bss_desc,
 398							 CIPHER_SUITE_CCMP)) {
 399
 400				if (mwifiex_is_wpa_oui_present
 401						(bss_desc, CIPHER_SUITE_TKIP)) {
 402					mwifiex_dbg(adapter, INFO,
 403						    "info: Disable 11n if AES\t"
 404						    "is not supported by AP\n");
 405					bss_desc->disable_11n = true;
 406				} else {
 407					return -1;
 408				}
 409			}
 410			return 0;
 411		} else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
 412			/* WPA2 enabled */
 413			if (((priv->adapter->config_bands & BAND_GN ||
 414			      priv->adapter->config_bands & BAND_AN) &&
 415			     bss_desc->bcn_ht_cap) &&
 416			    !mwifiex_is_rsn_oui_present(bss_desc,
 417							CIPHER_SUITE_CCMP)) {
 418
 419				if (mwifiex_is_rsn_oui_present
 420						(bss_desc, CIPHER_SUITE_TKIP)) {
 421					mwifiex_dbg(adapter, INFO,
 422						    "info: Disable 11n if AES\t"
 423						    "is not supported by AP\n");
 424					bss_desc->disable_11n = true;
 425				} else {
 426					return -1;
 427				}
 428			}
 429			return 0;
 430		} else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
 431			/* Ad-hoc AES enabled */
 432			return 0;
 433		} else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
 434			/* Dynamic WEP enabled */
 435			return 0;
 436		}
 437
 438		/* Security doesn't match */
 439		dbg_security_flags(ERROR, "failed", priv, bss_desc);
 440		return -1;
 441	}
 442
 443	/* Mode doesn't match */
 444	return -1;
 445}
 446
 447/*
 448 * This function creates a channel list for the driver to scan, based
 449 * on region/band information.
 450 *
 451 * This routine is used for any scan that is not provided with a
 452 * specific channel list to scan.
 453 */
 454static int
 455mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
 456				 const struct mwifiex_user_scan_cfg
 457							*user_scan_in,
 458				 struct mwifiex_chan_scan_param_set
 459							*scan_chan_list,
 460				 u8 filtered_scan)
 461{
 462	enum nl80211_band band;
 463	struct ieee80211_supported_band *sband;
 464	struct ieee80211_channel *ch;
 465	struct mwifiex_adapter *adapter = priv->adapter;
 466	int chan_idx = 0, i;
 467
 468	for (band = 0; (band < NUM_NL80211_BANDS) ; band++) {
 469
 470		if (!priv->wdev.wiphy->bands[band])
 471			continue;
 472
 473		sband = priv->wdev.wiphy->bands[band];
 474
 475		for (i = 0; (i < sband->n_channels) ; i++) {
 476			ch = &sband->channels[i];
 477			if (ch->flags & IEEE80211_CHAN_DISABLED)
 478				continue;
 479			scan_chan_list[chan_idx].radio_type = band;
 480
 481			if (user_scan_in &&
 482			    user_scan_in->chan_list[0].scan_time)
 483				scan_chan_list[chan_idx].max_scan_time =
 484					cpu_to_le16((u16) user_scan_in->
 485					chan_list[0].scan_time);
 486			else if ((ch->flags & IEEE80211_CHAN_NO_IR) ||
 487				 (ch->flags & IEEE80211_CHAN_RADAR))
 488				scan_chan_list[chan_idx].max_scan_time =
 489					cpu_to_le16(adapter->passive_scan_time);
 490			else
 491				scan_chan_list[chan_idx].max_scan_time =
 492					cpu_to_le16(adapter->active_scan_time);
 493
 494			if (ch->flags & IEEE80211_CHAN_NO_IR)
 495				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 496					|= (MWIFIEX_PASSIVE_SCAN |
 497					    MWIFIEX_HIDDEN_SSID_REPORT);
 498			else
 499				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 500					&= ~MWIFIEX_PASSIVE_SCAN;
 501			scan_chan_list[chan_idx].chan_number =
 502							(u32) ch->hw_value;
 503
 504			scan_chan_list[chan_idx].chan_scan_mode_bitmap
 505					|= MWIFIEX_DISABLE_CHAN_FILT;
 506
 507			if (filtered_scan &&
 508			    !((ch->flags & IEEE80211_CHAN_NO_IR) ||
 509			      (ch->flags & IEEE80211_CHAN_RADAR)))
 510				scan_chan_list[chan_idx].max_scan_time =
 511				cpu_to_le16(adapter->specific_scan_time);
 512
 513			chan_idx++;
 514		}
 515
 516	}
 517	return chan_idx;
 518}
 519
 520/* This function creates a channel list tlv for bgscan config, based
 521 * on region/band information.
 522 */
 523static int
 524mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv,
 525				   const struct mwifiex_bg_scan_cfg
 526						*bgscan_cfg_in,
 527				   struct mwifiex_chan_scan_param_set
 528						*scan_chan_list)
 529{
 530	enum nl80211_band band;
 531	struct ieee80211_supported_band *sband;
 532	struct ieee80211_channel *ch;
 533	struct mwifiex_adapter *adapter = priv->adapter;
 534	int chan_idx = 0, i;
 535
 536	for (band = 0; (band < NUM_NL80211_BANDS); band++) {
 537		if (!priv->wdev.wiphy->bands[band])
 538			continue;
 539
 540		sband = priv->wdev.wiphy->bands[band];
 541
 542		for (i = 0; (i < sband->n_channels) ; i++) {
 543			ch = &sband->channels[i];
 544			if (ch->flags & IEEE80211_CHAN_DISABLED)
 545				continue;
 546			scan_chan_list[chan_idx].radio_type = band;
 547
 548			if (bgscan_cfg_in->chan_list[0].scan_time)
 549				scan_chan_list[chan_idx].max_scan_time =
 550					cpu_to_le16((u16)bgscan_cfg_in->
 551					chan_list[0].scan_time);
 552			else if (ch->flags & IEEE80211_CHAN_NO_IR)
 553				scan_chan_list[chan_idx].max_scan_time =
 554					cpu_to_le16(adapter->passive_scan_time);
 555			else
 556				scan_chan_list[chan_idx].max_scan_time =
 557					cpu_to_le16(adapter->
 558						    specific_scan_time);
 559
 560			if (ch->flags & IEEE80211_CHAN_NO_IR)
 561				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 562					|= MWIFIEX_PASSIVE_SCAN;
 563			else
 564				scan_chan_list[chan_idx].chan_scan_mode_bitmap
 565					&= ~MWIFIEX_PASSIVE_SCAN;
 566
 567			scan_chan_list[chan_idx].chan_number =
 568							(u32)ch->hw_value;
 569			chan_idx++;
 570		}
 571	}
 572	return chan_idx;
 573}
 574
 575/* This function appends rate TLV to scan config command. */
 576static int
 577mwifiex_append_rate_tlv(struct mwifiex_private *priv,
 578			struct mwifiex_scan_cmd_config *scan_cfg_out,
 579			u8 radio)
 580{
 581	struct mwifiex_ie_types_rates_param_set *rates_tlv;
 582	u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
 583	u32 rates_size;
 584
 585	memset(rates, 0, sizeof(rates));
 586
 587	tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
 588
 589	if (priv->scan_request)
 590		rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
 591							     radio);
 592	else
 593		rates_size = mwifiex_get_supported_rates(priv, rates);
 594
 595	mwifiex_dbg(priv->adapter, CMD,
 596		    "info: SCAN_CMD: Rates size = %d\n",
 597		rates_size);
 598	rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
 599	rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
 600	rates_tlv->header.len = cpu_to_le16((u16) rates_size);
 601	memcpy(rates_tlv->rates, rates, rates_size);
 602	scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
 603
 604	return rates_size;
 605}
 606
 607/*
 608 * This function constructs and sends multiple scan config commands to
 609 * the firmware.
 610 *
 611 * Previous routines in the code flow have created a scan command configuration
 612 * with any requested TLVs.  This function splits the channel TLV into maximum
 613 * channels supported per scan lists and sends the portion of the channel TLV,
 614 * along with the other TLVs, to the firmware.
 615 */
 616static int
 617mwifiex_scan_channel_list(struct mwifiex_private *priv,
 618			  u32 max_chan_per_scan, u8 filtered_scan,
 619			  struct mwifiex_scan_cmd_config *scan_cfg_out,
 620			  struct mwifiex_ie_types_chan_list_param_set
 621			  *chan_tlv_out,
 622			  struct mwifiex_chan_scan_param_set *scan_chan_list)
 623{
 624	struct mwifiex_adapter *adapter = priv->adapter;
 625	int ret = 0;
 626	struct mwifiex_chan_scan_param_set *tmp_chan_list;
 627	struct mwifiex_chan_scan_param_set *start_chan;
 628	u32 tlv_idx, rates_size, cmd_no;
 629	u32 total_scan_time;
 630	u32 done_early;
 631	u8 radio_type;
 632
 633	if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
 634		mwifiex_dbg(priv->adapter, ERROR,
 635			    "info: Scan: Null detect: %p, %p, %p\n",
 636			    scan_cfg_out, chan_tlv_out, scan_chan_list);
 637		return -1;
 638	}
 639
 640	/* Check csa channel expiry before preparing scan list */
 641	mwifiex_11h_get_csa_closed_channel(priv);
 642
 643	chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
 644
 645	/* Set the temp channel struct pointer to the start of the desired
 646	   list */
 647	tmp_chan_list = scan_chan_list;
 648
 649	/* Loop through the desired channel list, sending a new firmware scan
 650	   commands for each max_chan_per_scan channels (or for 1,6,11
 651	   individually if configured accordingly) */
 652	while (tmp_chan_list->chan_number) {
 653
 654		tlv_idx = 0;
 655		total_scan_time = 0;
 656		radio_type = 0;
 657		chan_tlv_out->header.len = 0;
 658		start_chan = tmp_chan_list;
 659		done_early = false;
 660
 661		/*
 662		 * Construct the Channel TLV for the scan command.  Continue to
 663		 * insert channel TLVs until:
 664		 *   - the tlv_idx hits the maximum configured per scan command
 665		 *   - the next channel to insert is 0 (end of desired channel
 666		 *     list)
 667		 *   - done_early is set (controlling individual scanning of
 668		 *     1,6,11)
 669		 */
 670		while (tlv_idx < max_chan_per_scan &&
 671		       tmp_chan_list->chan_number && !done_early) {
 672
 673			if (tmp_chan_list->chan_number == priv->csa_chan) {
 674				tmp_chan_list++;
 675				continue;
 676			}
 677
 678			radio_type = tmp_chan_list->radio_type;
 679			mwifiex_dbg(priv->adapter, INFO,
 680				    "info: Scan: Chan(%3d), Radio(%d),\t"
 681				    "Mode(%d, %d), Dur(%d)\n",
 682				    tmp_chan_list->chan_number,
 683				    tmp_chan_list->radio_type,
 684				    tmp_chan_list->chan_scan_mode_bitmap
 685				    & MWIFIEX_PASSIVE_SCAN,
 686				    (tmp_chan_list->chan_scan_mode_bitmap
 687				    & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
 688				    le16_to_cpu(tmp_chan_list->max_scan_time));
 689
 690			/* Copy the current channel TLV to the command being
 691			   prepared */
 692			memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
 693			       tmp_chan_list,
 694			       sizeof(chan_tlv_out->chan_scan_param));
 695
 696			/* Increment the TLV header length by the size
 697			   appended */
 698			le16_unaligned_add_cpu(&chan_tlv_out->header.len,
 699					       sizeof(
 700						chan_tlv_out->chan_scan_param));
 701
 702			/*
 703			 * The tlv buffer length is set to the number of bytes
 704			 * of the between the channel tlv pointer and the start
 705			 * of the tlv buffer.  This compensates for any TLVs
 706			 * that were appended before the channel list.
 707			 */
 708			scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
 709							scan_cfg_out->tlv_buf);
 710
 711			/* Add the size of the channel tlv header and the data
 712			   length */
 713			scan_cfg_out->tlv_buf_len +=
 714				(sizeof(chan_tlv_out->header)
 715				 + le16_to_cpu(chan_tlv_out->header.len));
 716
 717			/* Increment the index to the channel tlv we are
 718			   constructing */
 719			tlv_idx++;
 720
 721			/* Count the total scan time per command */
 722			total_scan_time +=
 723				le16_to_cpu(tmp_chan_list->max_scan_time);
 724
 725			done_early = false;
 726
 727			/* Stop the loop if the *current* channel is in the
 728			   1,6,11 set and we are not filtering on a BSSID
 729			   or SSID. */
 730			if (!filtered_scan &&
 731			    (tmp_chan_list->chan_number == 1 ||
 732			     tmp_chan_list->chan_number == 6 ||
 733			     tmp_chan_list->chan_number == 11))
 734				done_early = true;
 735
 736			/* Increment the tmp pointer to the next channel to
 737			   be scanned */
 738			tmp_chan_list++;
 739
 740			/* Stop the loop if the *next* channel is in the 1,6,11
 741			   set.  This will cause it to be the only channel
 742			   scanned on the next interation */
 743			if (!filtered_scan &&
 744			    (tmp_chan_list->chan_number == 1 ||
 745			     tmp_chan_list->chan_number == 6 ||
 746			     tmp_chan_list->chan_number == 11))
 747				done_early = true;
 748		}
 749
 750		/* The total scan time should be less than scan command timeout
 751		   value */
 752		if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
 753			mwifiex_dbg(priv->adapter, ERROR,
 754				    "total scan time %dms\t"
 755				    "is over limit (%dms), scan skipped\n",
 756				    total_scan_time,
 757				    MWIFIEX_MAX_TOTAL_SCAN_TIME);
 758			ret = -1;
 759			break;
 760		}
 761
 762		rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
 763						     radio_type);
 764
 765		priv->adapter->scan_channels = start_chan;
 766
 767		/* Send the scan command to the firmware with the specified
 768		   cfg */
 769		if (priv->adapter->ext_scan)
 770			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
 771		else
 772			cmd_no = HostCmd_CMD_802_11_SCAN;
 773
 774		ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
 775				       0, scan_cfg_out, false);
 776
 777		/* rate IE is updated per scan command but same starting
 778		 * pointer is used each time so that rate IE from earlier
 779		 * scan_cfg_out->buf is overwritten with new one.
 780		 */
 781		scan_cfg_out->tlv_buf_len -=
 782			    sizeof(struct mwifiex_ie_types_header) + rates_size;
 783
 784		if (ret) {
 785			mwifiex_cancel_pending_scan_cmd(adapter);
 786			break;
 787		}
 788	}
 789
 790	if (ret)
 791		return -1;
 792
 793	return 0;
 794}
 795
 796/*
 797 * This function constructs a scan command configuration structure to use
 798 * in scan commands.
 799 *
 800 * Application layer or other functions can invoke network scanning
 801 * with a scan configuration supplied in a user scan configuration structure.
 802 * This structure is used as the basis of one or many scan command configuration
 803 * commands that are sent to the command processing module and eventually to the
 804 * firmware.
 805 *
 806 * This function creates a scan command configuration structure  based on the
 807 * following user supplied parameters (if present):
 808 *      - SSID filter
 809 *      - BSSID filter
 810 *      - Number of Probes to be sent
 811 *      - Channel list
 812 *
 813 * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
 814 * If the number of probes is not set, adapter default setting is used.
 815 */
 816static void
 817mwifiex_config_scan(struct mwifiex_private *priv,
 818		    const struct mwifiex_user_scan_cfg *user_scan_in,
 819		    struct mwifiex_scan_cmd_config *scan_cfg_out,
 820		    struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
 821		    struct mwifiex_chan_scan_param_set *scan_chan_list,
 822		    u8 *max_chan_per_scan, u8 *filtered_scan,
 823		    u8 *scan_current_only)
 824{
 825	struct mwifiex_adapter *adapter = priv->adapter;
 826	struct mwifiex_ie_types_num_probes *num_probes_tlv;
 827	struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
 828	struct mwifiex_ie_types_random_mac *random_mac_tlv;
 829	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
 830	struct mwifiex_ie_types_bssid_list *bssid_tlv;
 831	u8 *tlv_pos;
 832	u32 num_probes;
 833	u32 ssid_len;
 834	u32 chan_idx;
 835	u32 scan_type;
 836	u16 scan_dur;
 837	u8 channel;
 838	u8 radio_type;
 839	int i;
 840	u8 ssid_filter;
 841	struct mwifiex_ie_types_htcap *ht_cap;
 842	struct mwifiex_ie_types_bss_mode *bss_mode;
 843	const u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
 844
 845	/* The tlv_buf_len is calculated for each scan command.  The TLVs added
 846	   in this routine will be preserved since the routine that sends the
 847	   command will append channelTLVs at *chan_list_out.  The difference
 848	   between the *chan_list_out and the tlv_buf start will be used to
 849	   calculate the size of anything we add in this routine. */
 850	scan_cfg_out->tlv_buf_len = 0;
 851
 852	/* Running tlv pointer.  Assigned to chan_list_out at end of function
 853	   so later routines know where channels can be added to the command
 854	   buf */
 855	tlv_pos = scan_cfg_out->tlv_buf;
 856
 857	/* Initialize the scan as un-filtered; the flag is later set to TRUE
 858	   below if a SSID or BSSID filter is sent in the command */
 859	*filtered_scan = false;
 860
 861	/* Initialize the scan as not being only on the current channel.  If
 862	   the channel list is customized, only contains one channel, and is
 863	   the active channel, this is set true and data flow is not halted. */
 864	*scan_current_only = false;
 865
 866	if (user_scan_in) {
 867		u8 tmpaddr[ETH_ALEN];
 868
 869		/* Default the ssid_filter flag to TRUE, set false under
 870		   certain wildcard conditions and qualified by the existence
 871		   of an SSID list before marking the scan as filtered */
 872		ssid_filter = true;
 873
 874		/* Set the BSS type scan filter, use Adapter setting if
 875		   unset */
 876		scan_cfg_out->bss_mode =
 877			(u8)(user_scan_in->bss_mode ?: adapter->scan_mode);
 878
 879		/* Set the number of probes to send, use Adapter setting
 880		   if unset */
 881		num_probes = user_scan_in->num_probes ?: adapter->scan_probes;
 882
 883		/*
 884		 * Set the BSSID filter to the incoming configuration,
 885		 * if non-zero.  If not set, it will remain disabled
 886		 * (all zeros).
 887		 */
 888		memcpy(scan_cfg_out->specific_bssid,
 889		       user_scan_in->specific_bssid,
 890		       sizeof(scan_cfg_out->specific_bssid));
 891
 892		memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
 893
 894		if (adapter->ext_scan &&
 895		    !is_zero_ether_addr(tmpaddr)) {
 896			bssid_tlv =
 897				(struct mwifiex_ie_types_bssid_list *)tlv_pos;
 898			bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
 899			bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
 900			memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
 901			       ETH_ALEN);
 902			tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
 903		}
 904
 905		for (i = 0; i < user_scan_in->num_ssids; i++) {
 906			ssid_len = user_scan_in->ssid_list[i].ssid_len;
 907
 908			wildcard_ssid_tlv =
 909				(struct mwifiex_ie_types_wildcard_ssid_params *)
 910				tlv_pos;
 911			wildcard_ssid_tlv->header.type =
 912				cpu_to_le16(TLV_TYPE_WILDCARDSSID);
 913			wildcard_ssid_tlv->header.len = cpu_to_le16(
 914				(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
 915							 max_ssid_length)));
 916
 917			/*
 918			 * max_ssid_length = 0 tells firmware to perform
 919			 * specific scan for the SSID filled, whereas
 920			 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
 921			 * wildcard scan.
 922			 */
 923			if (ssid_len)
 924				wildcard_ssid_tlv->max_ssid_length = 0;
 925			else
 926				wildcard_ssid_tlv->max_ssid_length =
 927							IEEE80211_MAX_SSID_LEN;
 928
 929			if (!memcmp(user_scan_in->ssid_list[i].ssid,
 930				    "DIRECT-", 7))
 931				wildcard_ssid_tlv->max_ssid_length = 0xfe;
 932
 933			memcpy(wildcard_ssid_tlv->ssid,
 934			       user_scan_in->ssid_list[i].ssid, ssid_len);
 935
 936			tlv_pos += (sizeof(wildcard_ssid_tlv->header)
 937				+ le16_to_cpu(wildcard_ssid_tlv->header.len));
 938
 939			mwifiex_dbg(adapter, INFO,
 940				    "info: scan: ssid[%d]: %s, %d\n",
 941				    i, wildcard_ssid_tlv->ssid,
 942				    wildcard_ssid_tlv->max_ssid_length);
 943
 944			/* Empty wildcard ssid with a maxlen will match many or
 945			   potentially all SSIDs (maxlen == 32), therefore do
 946			   not treat the scan as
 947			   filtered. */
 948			if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
 949				ssid_filter = false;
 950		}
 951
 952		/*
 953		 *  The default number of channels sent in the command is low to
 954		 *  ensure the response buffer from the firmware does not
 955		 *  truncate scan results.  That is not an issue with an SSID
 956		 *  or BSSID filter applied to the scan results in the firmware.
 957		 */
 958		memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
 959		if ((i && ssid_filter) ||
 960		    !is_zero_ether_addr(tmpaddr))
 961			*filtered_scan = true;
 962
 963		if (user_scan_in->scan_chan_gap) {
 964			mwifiex_dbg(adapter, INFO,
 965				    "info: scan: channel gap = %d\n",
 966				    user_scan_in->scan_chan_gap);
 967			*max_chan_per_scan =
 968					MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
 969
 970			chan_gap_tlv = (void *)tlv_pos;
 971			chan_gap_tlv->header.type =
 972					 cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
 973			chan_gap_tlv->header.len =
 974				    cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
 975			chan_gap_tlv->chan_gap =
 976				     cpu_to_le16((user_scan_in->scan_chan_gap));
 977			tlv_pos +=
 978				  sizeof(struct mwifiex_ie_types_scan_chan_gap);
 979		}
 980
 981		if (!ether_addr_equal(user_scan_in->random_mac, zero_mac)) {
 982			random_mac_tlv = (void *)tlv_pos;
 983			random_mac_tlv->header.type =
 984					 cpu_to_le16(TLV_TYPE_RANDOM_MAC);
 985			random_mac_tlv->header.len =
 986				    cpu_to_le16(sizeof(random_mac_tlv->mac));
 987			ether_addr_copy(random_mac_tlv->mac,
 988					user_scan_in->random_mac);
 989			tlv_pos +=
 990				  sizeof(struct mwifiex_ie_types_random_mac);
 991		}
 992	} else {
 993		scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
 994		num_probes = adapter->scan_probes;
 995	}
 996
 997	/*
 998	 *  If a specific BSSID or SSID is used, the number of channels in the
 999	 *  scan command will be increased to the absolute maximum.
1000	 */
1001	if (*filtered_scan) {
1002		*max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1003	} else {
1004		if (!priv->media_connected)
1005			*max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
1006		else
1007			*max_chan_per_scan =
1008					MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD / 2;
1009	}
1010
1011	if (adapter->ext_scan) {
1012		bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
1013		bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
1014		bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
1015		bss_mode->bss_mode = scan_cfg_out->bss_mode;
1016		tlv_pos += sizeof(bss_mode->header) +
1017			   le16_to_cpu(bss_mode->header.len);
1018	}
1019
1020	/* If the input config or adapter has the number of Probes set,
1021	   add tlv */
1022	if (num_probes) {
1023
1024		mwifiex_dbg(adapter, INFO,
1025			    "info: scan: num_probes = %d\n",
1026			    num_probes);
1027
1028		num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
1029		num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
1030		num_probes_tlv->header.len =
1031			cpu_to_le16(sizeof(num_probes_tlv->num_probes));
1032		num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
1033
1034		tlv_pos += sizeof(num_probes_tlv->header) +
1035			le16_to_cpu(num_probes_tlv->header.len);
1036
1037	}
1038
1039	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
1040	    (priv->adapter->config_bands & BAND_GN ||
1041	     priv->adapter->config_bands & BAND_AN)) {
1042		ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
1043		memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
1044		ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1045		ht_cap->header.len =
1046				cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1047		radio_type =
1048			mwifiex_band_to_radio_type(priv->adapter->config_bands);
1049		mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
1050		tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
1051	}
1052
1053	/* Append vendor specific IE TLV */
1054	mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1055
1056	/*
1057	 * Set the output for the channel TLV to the address in the tlv buffer
1058	 *   past any TLVs that were added in this function (SSID, num_probes).
1059	 *   Channel TLVs will be added past this for each scan command,
1060	 *   preserving the TLVs that were previously added.
1061	 */
1062	*chan_list_out =
1063		(struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1064
1065	if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1066
1067		mwifiex_dbg(adapter, INFO,
1068			    "info: Scan: Using supplied channel list\n");
1069
1070		for (chan_idx = 0;
1071		     chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
1072		     user_scan_in->chan_list[chan_idx].chan_number;
1073		     chan_idx++) {
1074
1075			channel = user_scan_in->chan_list[chan_idx].chan_number;
1076			scan_chan_list[chan_idx].chan_number = channel;
1077
1078			radio_type =
1079				user_scan_in->chan_list[chan_idx].radio_type;
1080			scan_chan_list[chan_idx].radio_type = radio_type;
1081
1082			scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1083
1084			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1085				scan_chan_list[chan_idx].chan_scan_mode_bitmap
1086					|= (MWIFIEX_PASSIVE_SCAN |
1087					    MWIFIEX_HIDDEN_SSID_REPORT);
1088			else
1089				scan_chan_list[chan_idx].chan_scan_mode_bitmap
1090					&= ~MWIFIEX_PASSIVE_SCAN;
1091
1092			scan_chan_list[chan_idx].chan_scan_mode_bitmap
1093				|= MWIFIEX_DISABLE_CHAN_FILT;
1094
1095			if (user_scan_in->chan_list[chan_idx].scan_time) {
1096				scan_dur = (u16) user_scan_in->
1097					chan_list[chan_idx].scan_time;
1098			} else {
1099				if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1100					scan_dur = adapter->passive_scan_time;
1101				else if (*filtered_scan)
1102					scan_dur = adapter->specific_scan_time;
1103				else
1104					scan_dur = adapter->active_scan_time;
1105			}
1106
1107			scan_chan_list[chan_idx].min_scan_time =
1108				cpu_to_le16(scan_dur);
1109			scan_chan_list[chan_idx].max_scan_time =
1110				cpu_to_le16(scan_dur);
1111		}
1112
1113		/* Check if we are only scanning the current channel */
1114		if ((chan_idx == 1) &&
1115		    (user_scan_in->chan_list[0].chan_number ==
1116		     priv->curr_bss_params.bss_descriptor.channel)) {
1117			*scan_current_only = true;
1118			mwifiex_dbg(adapter, INFO,
1119				    "info: Scan: Scanning current channel only\n");
1120		}
1121	} else {
1122		mwifiex_dbg(adapter, INFO,
1123			    "info: Scan: Creating full region channel list\n");
1124		mwifiex_scan_create_channel_list(priv, user_scan_in,
1125						 scan_chan_list,
1126						 *filtered_scan);
1127	}
1128
1129}
1130
1131/*
1132 * This function inspects the scan response buffer for pointers to
1133 * expected TLVs.
1134 *
1135 * TLVs can be included at the end of the scan response BSS information.
1136 *
1137 * Data in the buffer is parsed pointers to TLVs that can potentially
1138 * be passed back in the response.
1139 */
1140static void
1141mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1142				     struct mwifiex_ie_types_data *tlv,
1143				     u32 tlv_buf_size, u32 req_tlv_type,
1144				     struct mwifiex_ie_types_data **tlv_data)
1145{
1146	struct mwifiex_ie_types_data *current_tlv;
1147	u32 tlv_buf_left;
1148	u32 tlv_type;
1149	u32 tlv_len;
1150
1151	current_tlv = tlv;
1152	tlv_buf_left = tlv_buf_size;
1153	*tlv_data = NULL;
1154
1155	mwifiex_dbg(adapter, INFO,
1156		    "info: SCAN_RESP: tlv_buf_size = %d\n",
1157		    tlv_buf_size);
1158
1159	while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1160
1161		tlv_type = le16_to_cpu(current_tlv->header.type);
1162		tlv_len = le16_to_cpu(current_tlv->header.len);
1163
1164		if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1165			mwifiex_dbg(adapter, ERROR,
1166				    "SCAN_RESP: TLV buffer corrupt\n");
1167			break;
1168		}
1169
1170		if (req_tlv_type == tlv_type) {
1171			switch (tlv_type) {
1172			case TLV_TYPE_TSFTIMESTAMP:
1173				mwifiex_dbg(adapter, INFO,
1174					    "info: SCAN_RESP: TSF\t"
1175					    "timestamp TLV, len = %d\n",
1176					    tlv_len);
1177				*tlv_data = current_tlv;
1178				break;
1179			case TLV_TYPE_CHANNELBANDLIST:
1180				mwifiex_dbg(adapter, INFO,
1181					    "info: SCAN_RESP: channel\t"
1182					    "band list TLV, len = %d\n",
1183					    tlv_len);
1184				*tlv_data = current_tlv;
1185				break;
1186			default:
1187				mwifiex_dbg(adapter, ERROR,
1188					    "SCAN_RESP: unhandled TLV = %d\n",
1189					    tlv_type);
1190				/* Give up, this seems corrupted */
1191				return;
1192			}
1193		}
1194
1195		if (*tlv_data)
1196			break;
1197
1198
1199		tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1200		current_tlv =
1201			(struct mwifiex_ie_types_data *) (current_tlv->data +
1202							  tlv_len);
1203
1204	}			/* while */
1205}
1206
1207/*
1208 * This function parses provided beacon buffer and updates
1209 * respective fields in bss descriptor structure.
1210 */
1211int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1212				    struct mwifiex_bssdescriptor *bss_entry)
1213{
1214	int ret = 0;
1215	u8 element_id;
1216	struct ieee_types_fh_param_set *fh_param_set;
1217	struct ieee_types_ds_param_set *ds_param_set;
1218	struct ieee_types_cf_param_set *cf_param_set;
1219	struct ieee_types_ibss_param_set *ibss_param_set;
1220	u8 *current_ptr;
1221	u8 *rate;
1222	u8 element_len;
1223	u16 total_ie_len;
1224	u8 bytes_to_copy;
1225	u8 rate_size;
1226	u8 found_data_rate_ie;
1227	u32 bytes_left;
1228	struct ieee_types_vendor_specific *vendor_ie;
1229	const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1230	const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1231
1232	found_data_rate_ie = false;
1233	rate_size = 0;
1234	current_ptr = bss_entry->beacon_buf;
1235	bytes_left = bss_entry->beacon_buf_size;
1236
1237	/* Process variable IE */
1238	while (bytes_left >= 2) {
1239		element_id = *current_ptr;
1240		element_len = *(current_ptr + 1);
1241		total_ie_len = element_len + sizeof(struct ieee_types_header);
1242
1243		if (bytes_left < total_ie_len) {
1244			mwifiex_dbg(adapter, ERROR,
1245				    "err: InterpretIE: in processing\t"
1246				    "IE, bytes left < IE length\n");
1247			return -EINVAL;
1248		}
1249		switch (element_id) {
1250		case WLAN_EID_SSID:
1251			if (element_len > IEEE80211_MAX_SSID_LEN)
1252				return -EINVAL;
1253			bss_entry->ssid.ssid_len = element_len;
1254			memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1255			       element_len);
1256			mwifiex_dbg(adapter, INFO,
1257				    "info: InterpretIE: ssid: %-32s\n",
1258				    bss_entry->ssid.ssid);
1259			break;
1260
1261		case WLAN_EID_SUPP_RATES:
1262			if (element_len > MWIFIEX_SUPPORTED_RATES)
1263				return -EINVAL;
1264			memcpy(bss_entry->data_rates, current_ptr + 2,
1265			       element_len);
1266			memcpy(bss_entry->supported_rates, current_ptr + 2,
1267			       element_len);
1268			rate_size = element_len;
1269			found_data_rate_ie = true;
1270			break;
1271
1272		case WLAN_EID_FH_PARAMS:
1273			if (element_len + 2 < sizeof(*fh_param_set))
1274				return -EINVAL;
1275			fh_param_set =
1276				(struct ieee_types_fh_param_set *) current_ptr;
1277			memcpy(&bss_entry->phy_param_set.fh_param_set,
1278			       fh_param_set,
1279			       sizeof(struct ieee_types_fh_param_set));
1280			break;
1281
1282		case WLAN_EID_DS_PARAMS:
1283			if (element_len + 2 < sizeof(*ds_param_set))
1284				return -EINVAL;
1285			ds_param_set =
1286				(struct ieee_types_ds_param_set *) current_ptr;
1287
1288			bss_entry->channel = ds_param_set->current_chan;
1289
1290			memcpy(&bss_entry->phy_param_set.ds_param_set,
1291			       ds_param_set,
1292			       sizeof(struct ieee_types_ds_param_set));
1293			break;
1294
1295		case WLAN_EID_CF_PARAMS:
1296			if (element_len + 2 < sizeof(*cf_param_set))
1297				return -EINVAL;
1298			cf_param_set =
1299				(struct ieee_types_cf_param_set *) current_ptr;
1300			memcpy(&bss_entry->ss_param_set.cf_param_set,
1301			       cf_param_set,
1302			       sizeof(struct ieee_types_cf_param_set));
1303			break;
1304
1305		case WLAN_EID_IBSS_PARAMS:
1306			if (element_len + 2 < sizeof(*ibss_param_set))
1307				return -EINVAL;
1308			ibss_param_set =
1309				(struct ieee_types_ibss_param_set *)
1310				current_ptr;
1311			memcpy(&bss_entry->ss_param_set.ibss_param_set,
1312			       ibss_param_set,
1313			       sizeof(struct ieee_types_ibss_param_set));
1314			break;
1315
1316		case WLAN_EID_ERP_INFO:
1317			if (!element_len)
1318				return -EINVAL;
1319			bss_entry->erp_flags = *(current_ptr + 2);
1320			break;
1321
1322		case WLAN_EID_PWR_CONSTRAINT:
1323			if (!element_len)
1324				return -EINVAL;
1325			bss_entry->local_constraint = *(current_ptr + 2);
1326			bss_entry->sensed_11h = true;
1327			break;
1328
1329		case WLAN_EID_CHANNEL_SWITCH:
1330			bss_entry->chan_sw_ie_present = true;
1331			/* fall through */
1332		case WLAN_EID_PWR_CAPABILITY:
1333		case WLAN_EID_TPC_REPORT:
1334		case WLAN_EID_QUIET:
1335			bss_entry->sensed_11h = true;
1336		    break;
1337
1338		case WLAN_EID_EXT_SUPP_RATES:
1339			/*
1340			 * Only process extended supported rate
1341			 * if data rate is already found.
1342			 * Data rate IE should come before
1343			 * extended supported rate IE
1344			 */
1345			if (found_data_rate_ie) {
1346				if ((element_len + rate_size) >
1347				    MWIFIEX_SUPPORTED_RATES)
1348					bytes_to_copy =
1349						(MWIFIEX_SUPPORTED_RATES -
1350						 rate_size);
1351				else
1352					bytes_to_copy = element_len;
1353
1354				rate = (u8 *) bss_entry->data_rates;
1355				rate += rate_size;
1356				memcpy(rate, current_ptr + 2, bytes_to_copy);
1357
1358				rate = (u8 *) bss_entry->supported_rates;
1359				rate += rate_size;
1360				memcpy(rate, current_ptr + 2, bytes_to_copy);
1361			}
1362			break;
1363
1364		case WLAN_EID_VENDOR_SPECIFIC:
1365			vendor_ie = (struct ieee_types_vendor_specific *)
1366					current_ptr;
1367
1368			/* 802.11 requires at least 3-byte OUI. */
1369			if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
1370				return -EINVAL;
1371
1372			/* Not long enough for a match? Skip it. */
1373			if (element_len < sizeof(wpa_oui))
1374				break;
1375
1376			if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
1377				    sizeof(wpa_oui))) {
1378				bss_entry->bcn_wpa_ie =
1379					(struct ieee_types_vendor_specific *)
1380					current_ptr;
1381				bss_entry->wpa_offset = (u16)
1382					(current_ptr - bss_entry->beacon_buf);
1383			} else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
1384				    sizeof(wmm_oui))) {
1385				if (total_ie_len ==
1386				    sizeof(struct ieee_types_wmm_parameter) ||
1387				    total_ie_len ==
1388				    sizeof(struct ieee_types_wmm_info))
1389					/*
1390					 * Only accept and copy the WMM IE if
1391					 * it matches the size expected for the
1392					 * WMM Info IE or the WMM Parameter IE.
1393					 */
1394					memcpy((u8 *) &bss_entry->wmm_ie,
1395					       current_ptr, total_ie_len);
1396			}
1397			break;
1398		case WLAN_EID_RSN:
1399			bss_entry->bcn_rsn_ie =
1400				(struct ieee_types_generic *) current_ptr;
1401			bss_entry->rsn_offset = (u16) (current_ptr -
1402							bss_entry->beacon_buf);
1403			break;
1404		case WLAN_EID_BSS_AC_ACCESS_DELAY:
1405			bss_entry->bcn_wapi_ie =
1406				(struct ieee_types_generic *) current_ptr;
1407			bss_entry->wapi_offset = (u16) (current_ptr -
1408							bss_entry->beacon_buf);
1409			break;
1410		case WLAN_EID_HT_CAPABILITY:
1411			bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1412					(current_ptr +
1413					sizeof(struct ieee_types_header));
1414			bss_entry->ht_cap_offset = (u16) (current_ptr +
1415					sizeof(struct ieee_types_header) -
1416					bss_entry->beacon_buf);
1417			break;
1418		case WLAN_EID_HT_OPERATION:
1419			bss_entry->bcn_ht_oper =
1420				(struct ieee80211_ht_operation *)(current_ptr +
1421					sizeof(struct ieee_types_header));
1422			bss_entry->ht_info_offset = (u16) (current_ptr +
1423					sizeof(struct ieee_types_header) -
1424					bss_entry->beacon_buf);
1425			break;
1426		case WLAN_EID_VHT_CAPABILITY:
1427			bss_entry->disable_11ac = false;
1428			bss_entry->bcn_vht_cap =
1429				(void *)(current_ptr +
1430					 sizeof(struct ieee_types_header));
1431			bss_entry->vht_cap_offset =
1432					(u16)((u8 *)bss_entry->bcn_vht_cap -
1433					      bss_entry->beacon_buf);
1434			break;
1435		case WLAN_EID_VHT_OPERATION:
1436			bss_entry->bcn_vht_oper =
1437				(void *)(current_ptr +
1438					 sizeof(struct ieee_types_header));
1439			bss_entry->vht_info_offset =
1440					(u16)((u8 *)bss_entry->bcn_vht_oper -
1441					      bss_entry->beacon_buf);
1442			break;
1443		case WLAN_EID_BSS_COEX_2040:
1444			bss_entry->bcn_bss_co_2040 = current_ptr;
1445			bss_entry->bss_co_2040_offset =
1446				(u16) (current_ptr - bss_entry->beacon_buf);
1447			break;
1448		case WLAN_EID_EXT_CAPABILITY:
1449			bss_entry->bcn_ext_cap = current_ptr;
1450			bss_entry->ext_cap_offset =
1451				(u16) (current_ptr - bss_entry->beacon_buf);
1452			break;
1453		case WLAN_EID_OPMODE_NOTIF:
1454			bss_entry->oper_mode = (void *)current_ptr;
1455			bss_entry->oper_mode_offset =
1456					(u16)((u8 *)bss_entry->oper_mode -
1457					      bss_entry->beacon_buf);
1458			break;
1459		default:
1460			break;
1461		}
1462
1463		current_ptr += element_len + 2;
1464
1465		/* Need to account for IE ID and IE Len */
1466		bytes_left -= (element_len + 2);
1467
1468	}	/* while (bytes_left > 2) */
1469	return ret;
1470}
1471
1472/*
1473 * This function converts radio type scan parameter to a band configuration
1474 * to be used in join command.
1475 */
1476static u8
1477mwifiex_radio_type_to_band(u8 radio_type)
1478{
1479	switch (radio_type) {
1480	case HostCmd_SCAN_RADIO_TYPE_A:
1481		return BAND_A;
1482	case HostCmd_SCAN_RADIO_TYPE_BG:
1483	default:
1484		return BAND_G;
1485	}
1486}
1487
1488/*
1489 * This is an internal function used to start a scan based on an input
1490 * configuration.
1491 *
1492 * This uses the input user scan configuration information when provided in
1493 * order to send the appropriate scan commands to firmware to populate or
1494 * update the internal driver scan table.
1495 */
1496int mwifiex_scan_networks(struct mwifiex_private *priv,
1497			  const struct mwifiex_user_scan_cfg *user_scan_in)
1498{
1499	int ret;
1500	struct mwifiex_adapter *adapter = priv->adapter;
1501	struct cmd_ctrl_node *cmd_node;
1502	union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1503	struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1504	struct mwifiex_chan_scan_param_set *scan_chan_list;
1505	u8 filtered_scan;
1506	u8 scan_current_chan_only;
1507	u8 max_chan_per_scan;
1508
1509	if (adapter->scan_processing) {
1510		mwifiex_dbg(adapter, WARN,
1511			    "cmd: Scan already in process...\n");
1512		return -EBUSY;
1513	}
1514
1515	if (priv->scan_block) {
1516		mwifiex_dbg(adapter, WARN,
1517			    "cmd: Scan is blocked during association...\n");
1518		return -EBUSY;
1519	}
1520
1521	if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
1522	    test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
1523		mwifiex_dbg(adapter, ERROR,
1524			    "Ignore scan. Card removed or firmware in bad state\n");
1525		return -EFAULT;
1526	}
1527
1528	spin_lock_bh(&adapter->mwifiex_cmd_lock);
1529	adapter->scan_processing = true;
1530	spin_unlock_bh(&adapter->mwifiex_cmd_lock);
1531
1532	scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1533			       GFP_KERNEL);
1534	if (!scan_cfg_out) {
1535		ret = -ENOMEM;
1536		goto done;
1537	}
1538
1539	scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1540				 sizeof(struct mwifiex_chan_scan_param_set),
1541				 GFP_KERNEL);
1542	if (!scan_chan_list) {
1543		kfree(scan_cfg_out);
1544		ret = -ENOMEM;
1545		goto done;
1546	}
1547
1548	mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1549			    &chan_list_out, scan_chan_list, &max_chan_per_scan,
1550			    &filtered_scan, &scan_current_chan_only);
1551
1552	ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1553					&scan_cfg_out->config, chan_list_out,
1554					scan_chan_list);
1555
1556	/* Get scan command from scan_pending_q and put to cmd_pending_q */
1557	if (!ret) {
1558		spin_lock_bh(&adapter->scan_pending_q_lock);
1559		if (!list_empty(&adapter->scan_pending_q)) {
1560			cmd_node = list_first_entry(&adapter->scan_pending_q,
1561						    struct cmd_ctrl_node, list);
1562			list_del(&cmd_node->list);
1563			spin_unlock_bh(&adapter->scan_pending_q_lock);
1564			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
1565			queue_work(adapter->workqueue, &adapter->main_work);
1566
1567			/* Perform internal scan synchronously */
1568			if (!priv->scan_request) {
1569				mwifiex_dbg(adapter, INFO,
1570					    "wait internal scan\n");
1571				mwifiex_wait_queue_complete(adapter, cmd_node);
1572			}
1573		} else {
1574			spin_unlock_bh(&adapter->scan_pending_q_lock);
1575		}
1576	}
1577
1578	kfree(scan_cfg_out);
1579	kfree(scan_chan_list);
1580done:
1581	if (ret) {
1582		spin_lock_bh(&adapter->mwifiex_cmd_lock);
1583		adapter->scan_processing = false;
1584		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
1585	}
1586	return ret;
1587}
1588
1589/*
1590 * This function prepares a scan command to be sent to the firmware.
1591 *
1592 * This uses the scan command configuration sent to the command processing
1593 * module in command preparation stage to configure a scan command structure
1594 * to send to firmware.
1595 *
1596 * The fixed fields specifying the BSS type and BSSID filters as well as a
1597 * variable number/length of TLVs are sent in the command to firmware.
1598 *
1599 * Preparation also includes -
1600 *      - Setting command ID, and proper size
1601 *      - Ensuring correct endian-ness
1602 */
1603int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1604			    struct mwifiex_scan_cmd_config *scan_cfg)
1605{
1606	struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1607
1608	/* Set fixed field variables in scan command */
1609	scan_cmd->bss_mode = scan_cfg->bss_mode;
1610	memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1611	       sizeof(scan_cmd->bssid));
1612	memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1613
1614	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1615
1616	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1617	cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1618					  + sizeof(scan_cmd->bssid)
1619					  + scan_cfg->tlv_buf_len + S_DS_GEN));
1620
1621	return 0;
1622}
1623
1624/*
1625 * This function checks compatibility of requested network with current
1626 * driver settings.
1627 */
1628int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1629					struct mwifiex_bssdescriptor *bss_desc)
1630{
1631	int ret = -1;
1632
1633	if (!bss_desc)
1634		return -1;
1635
1636	if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1637			     (u16) bss_desc->channel, 0))) {
1638		switch (priv->bss_mode) {
1639		case NL80211_IFTYPE_STATION:
1640		case NL80211_IFTYPE_ADHOC:
1641			ret = mwifiex_is_network_compatible(priv, bss_desc,
1642							    priv->bss_mode);
1643			if (ret)
1644				mwifiex_dbg(priv->adapter, ERROR,
1645					    "Incompatible network settings\n");
1646			break;
1647		default:
1648			ret = 0;
1649		}
1650	}
1651
1652	return ret;
1653}
1654
1655/* This function checks if SSID string contains all zeroes or length is zero */
1656static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1657{
1658	int idx;
1659
1660	for (idx = 0; idx < ssid->ssid_len; idx++) {
1661		if (ssid->ssid[idx])
1662			return false;
1663	}
1664
1665	return true;
1666}
1667
1668/* This function checks if any hidden SSID found in passive scan channels
1669 * and save those channels for specific SSID active scan
1670 */
1671static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1672					     struct cfg80211_bss *bss)
1673{
1674	struct mwifiex_bssdescriptor *bss_desc;
1675	int ret;
1676	int chid;
1677
1678	/* Allocate and fill new bss descriptor */
1679	bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1680	if (!bss_desc)
1681		return -ENOMEM;
1682
1683	ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1684	if (ret)
1685		goto done;
1686
1687	if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1688		mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1689		for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1690			if (priv->hidden_chan[chid].chan_number ==
1691			    bss->channel->hw_value)
1692				break;
1693
1694			if (!priv->hidden_chan[chid].chan_number) {
1695				priv->hidden_chan[chid].chan_number =
1696					bss->channel->hw_value;
1697				priv->hidden_chan[chid].radio_type =
1698					bss->channel->band;
1699				priv->hidden_chan[chid].scan_type =
1700					MWIFIEX_SCAN_TYPE_ACTIVE;
1701				break;
1702			}
1703		}
1704	}
1705
1706done:
1707	/* beacon_ie buffer was allocated in function
1708	 * mwifiex_fill_new_bss_desc(). Free it now.
1709	 */
1710	kfree(bss_desc->beacon_buf);
1711	kfree(bss_desc);
1712	return 0;
1713}
1714
1715static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1716					  struct cfg80211_bss *bss)
1717{
1718	struct mwifiex_bssdescriptor *bss_desc;
1719	int ret;
1720
1721	/* Allocate and fill new bss descriptor */
1722	bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1723	if (!bss_desc)
1724		return -ENOMEM;
1725
1726	ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1727	if (ret)
1728		goto done;
1729
1730	ret = mwifiex_check_network_compatibility(priv, bss_desc);
1731	if (ret)
1732		goto done;
1733
1734	spin_lock_bh(&priv->curr_bcn_buf_lock);
1735	/* Make a copy of current BSSID descriptor */
1736	memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1737	       sizeof(priv->curr_bss_params.bss_descriptor));
1738
1739	/* The contents of beacon_ie will be copied to its own buffer
1740	 * in mwifiex_save_curr_bcn()
1741	 */
1742	mwifiex_save_curr_bcn(priv);
1743	spin_unlock_bh(&priv->curr_bcn_buf_lock);
1744
1745done:
1746	/* beacon_ie buffer was allocated in function
1747	 * mwifiex_fill_new_bss_desc(). Free it now.
1748	 */
1749	kfree(bss_desc->beacon_buf);
1750	kfree(bss_desc);
1751	return 0;
1752}
1753
1754static int
1755mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1756				  u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1757				  bool ext_scan, s32 rssi_val)
1758{
1759	struct mwifiex_adapter *adapter = priv->adapter;
1760	struct mwifiex_chan_freq_power *cfp;
1761	struct cfg80211_bss *bss;
1762	u8 bssid[ETH_ALEN];
1763	s32 rssi;
1764	const u8 *ie_buf;
1765	size_t ie_len;
1766	u16 channel = 0;
1767	u16 beacon_size = 0;
1768	u32 curr_bcn_bytes;
1769	u32 freq;
1770	u16 beacon_period;
1771	u16 cap_info_bitmap;
1772	u8 *current_ptr;
1773	u64 timestamp;
1774	struct mwifiex_fixed_bcn_param *bcn_param;
1775	struct mwifiex_bss_priv *bss_priv;
1776
1777	if (*bytes_left >= sizeof(beacon_size)) {
1778		/* Extract & convert beacon size from command buffer */
1779		beacon_size = get_unaligned_le16((*bss_info));
1780		*bytes_left -= sizeof(beacon_size);
1781		*bss_info += sizeof(beacon_size);
1782	}
1783
1784	if (!beacon_size || beacon_size > *bytes_left) {
1785		*bss_info += *bytes_left;
1786		*bytes_left = 0;
1787		return -EFAULT;
1788	}
1789
1790	/* Initialize the current working beacon pointer for this BSS
1791	 * iteration
1792	 */
1793	current_ptr = *bss_info;
1794
1795	/* Advance the return beacon pointer past the current beacon */
1796	*bss_info += beacon_size;
1797	*bytes_left -= beacon_size;
1798
1799	curr_bcn_bytes = beacon_size;
1800
1801	/* First 5 fields are bssid, RSSI(for legacy scan only),
1802	 * time stamp, beacon interval, and capability information
1803	 */
1804	if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1805	    sizeof(struct mwifiex_fixed_bcn_param)) {
1806		mwifiex_dbg(adapter, ERROR,
1807			    "InterpretIE: not enough bytes left\n");
1808		return -EFAULT;
1809	}
1810
1811	memcpy(bssid, current_ptr, ETH_ALEN);
1812	current_ptr += ETH_ALEN;
1813	curr_bcn_bytes -= ETH_ALEN;
1814
1815	if (!ext_scan) {
1816		rssi = (s32) *current_ptr;
1817		rssi = (-rssi) * 100;		/* Convert dBm to mBm */
1818		current_ptr += sizeof(u8);
1819		curr_bcn_bytes -= sizeof(u8);
1820		mwifiex_dbg(adapter, INFO,
1821			    "info: InterpretIE: RSSI=%d\n", rssi);
1822	} else {
1823		rssi = rssi_val;
1824	}
1825
1826	bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1827	current_ptr += sizeof(*bcn_param);
1828	curr_bcn_bytes -= sizeof(*bcn_param);
1829
1830	timestamp = le64_to_cpu(bcn_param->timestamp);
1831	beacon_period = le16_to_cpu(bcn_param->beacon_period);
1832
1833	cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1834	mwifiex_dbg(adapter, INFO,
1835		    "info: InterpretIE: capabilities=0x%X\n",
1836		    cap_info_bitmap);
1837
1838	/* Rest of the current buffer are IE's */
1839	ie_buf = current_ptr;
1840	ie_len = curr_bcn_bytes;
1841	mwifiex_dbg(adapter, INFO,
1842		    "info: InterpretIE: IELength for this AP = %d\n",
1843		    curr_bcn_bytes);
1844
1845	while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1846		u8 element_id, element_len;
1847
1848		element_id = *current_ptr;
1849		element_len = *(current_ptr + 1);
1850		if (curr_bcn_bytes < element_len +
1851				sizeof(struct ieee_types_header)) {
1852			mwifiex_dbg(adapter, ERROR,
1853				    "%s: bytes left < IE length\n", __func__);
1854			return -EFAULT;
1855		}
1856		if (element_id == WLAN_EID_DS_PARAMS) {
1857			channel = *(current_ptr +
1858				    sizeof(struct ieee_types_header));
1859			break;
1860		}
1861
1862		current_ptr += element_len + sizeof(struct ieee_types_header);
1863		curr_bcn_bytes -= element_len +
1864					sizeof(struct ieee_types_header);
1865	}
1866
1867	if (channel) {
1868		struct ieee80211_channel *chan;
1869		u8 band;
1870
1871		/* Skip entry if on csa closed channel */
1872		if (channel == priv->csa_chan) {
1873			mwifiex_dbg(adapter, WARN,
1874				    "Dropping entry on csa closed channel\n");
1875			return 0;
1876		}
1877
1878		band = BAND_G;
1879		if (radio_type)
1880			band = mwifiex_radio_type_to_band(*radio_type &
1881							  (BIT(0) | BIT(1)));
1882
1883		cfp = mwifiex_get_cfp(priv, band, channel, 0);
1884
1885		freq = cfp ? cfp->freq : 0;
1886
1887		chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1888
1889		if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1890			bss = cfg80211_inform_bss(priv->wdev.wiphy,
1891					    chan, CFG80211_BSS_FTYPE_UNKNOWN,
1892					    bssid, timestamp,
1893					    cap_info_bitmap, beacon_period,
1894					    ie_buf, ie_len, rssi, GFP_KERNEL);
1895			if (bss) {
1896				bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1897				bss_priv->band = band;
1898				bss_priv->fw_tsf = fw_tsf;
1899				if (priv->media_connected &&
1900				    !memcmp(bssid, priv->curr_bss_params.
1901					    bss_descriptor.mac_address,
1902					    ETH_ALEN))
1903					mwifiex_update_curr_bss_params(priv,
1904								       bss);
1905
1906				if ((chan->flags & IEEE80211_CHAN_RADAR) ||
1907				    (chan->flags & IEEE80211_CHAN_NO_IR)) {
1908					mwifiex_dbg(adapter, INFO,
1909						    "radar or passive channel %d\n",
1910						    channel);
1911					mwifiex_save_hidden_ssid_channels(priv,
1912									  bss);
1913				}
1914
1915				cfg80211_put_bss(priv->wdev.wiphy, bss);
1916			}
1917		}
1918	} else {
1919		mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1920	}
1921
1922	return 0;
1923}
1924
1925static void mwifiex_complete_scan(struct mwifiex_private *priv)
1926{
1927	struct mwifiex_adapter *adapter = priv->adapter;
1928
1929	adapter->survey_idx = 0;
1930	if (adapter->curr_cmd->wait_q_enabled) {
1931		adapter->cmd_wait_q.status = 0;
1932		if (!priv->scan_request) {
1933			mwifiex_dbg(adapter, INFO,
1934				    "complete internal scan\n");
1935			mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1936		}
1937	}
1938}
1939
1940/* This function checks if any hidden SSID found in passive scan channels
1941 * and do specific SSID active scan for those channels
1942 */
1943static int
1944mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
1945{
1946	int ret;
1947	struct mwifiex_adapter *adapter = priv->adapter;
1948	u8 id = 0;
1949	struct mwifiex_user_scan_cfg  *user_scan_cfg;
1950
1951	if (adapter->active_scan_triggered || !priv->scan_request ||
1952	    priv->scan_aborting) {
1953		adapter->active_scan_triggered = false;
1954		return 0;
1955	}
1956
1957	if (!priv->hidden_chan[0].chan_number) {
1958		mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
1959		return 0;
1960	}
1961	user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1962
1963	if (!user_scan_cfg)
1964		return -ENOMEM;
1965
1966	for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
1967		if (!priv->hidden_chan[id].chan_number)
1968			break;
1969		memcpy(&user_scan_cfg->chan_list[id],
1970		       &priv->hidden_chan[id],
1971		       sizeof(struct mwifiex_user_scan_chan));
1972	}
1973
1974	adapter->active_scan_triggered = true;
1975	if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
1976		ether_addr_copy(user_scan_cfg->random_mac,
1977				priv->scan_request->mac_addr);
1978	user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
1979	user_scan_cfg->ssid_list = priv->scan_request->ssids;
1980
1981	ret = mwifiex_scan_networks(priv, user_scan_cfg);
1982	kfree(user_scan_cfg);
1983
1984	memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
1985
1986	if (ret) {
1987		dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1988		return ret;
1989	}
1990
1991	return 0;
1992}
1993static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1994{
1995	struct mwifiex_adapter *adapter = priv->adapter;
1996	struct cmd_ctrl_node *cmd_node;
1997
1998	spin_lock_bh(&adapter->scan_pending_q_lock);
1999	if (list_empty(&adapter->scan_pending_q)) {
2000		spin_unlock_bh(&adapter->scan_pending_q_lock);
2001
2002		spin_lock_bh(&adapter->mwifiex_cmd_lock);
2003		adapter->scan_processing = false;
2004		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
2005
2006		mwifiex_active_scan_req_for_passive_chan(priv);
2007
2008		if (!adapter->ext_scan)
2009			mwifiex_complete_scan(priv);
2010
2011		if (priv->scan_request) {
2012			struct cfg80211_scan_info info = {
2013				.aborted = false,
2014			};
2015
2016			mwifiex_dbg(adapter, INFO,
2017				    "info: notifying scan done\n");
2018			cfg80211_scan_done(priv->scan_request, &info);
2019			priv->scan_request = NULL;
2020			priv->scan_aborting = false;
2021		} else {
2022			priv->scan_aborting = false;
2023			mwifiex_dbg(adapter, INFO,
2024				    "info: scan already aborted\n");
2025		}
2026	} else if ((priv->scan_aborting && !priv->scan_request) ||
2027		   priv->scan_block) {
2028		spin_unlock_bh(&adapter->scan_pending_q_lock);
2029
2030		mwifiex_cancel_pending_scan_cmd(adapter);
2031
2032		spin_lock_bh(&adapter->mwifiex_cmd_lock);
2033		adapter->scan_processing = false;
2034		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
2035
2036		if (!adapter->active_scan_triggered) {
2037			if (priv->scan_request) {
2038				struct cfg80211_scan_info info = {
2039					.aborted = true,
2040				};
2041
2042				mwifiex_dbg(adapter, INFO,
2043					    "info: aborting scan\n");
2044				cfg80211_scan_done(priv->scan_request, &info);
2045				priv->scan_request = NULL;
2046				priv->scan_aborting = false;
2047			} else {
2048				priv->scan_aborting = false;
2049				mwifiex_dbg(adapter, INFO,
2050					    "info: scan already aborted\n");
2051			}
2052		}
2053	} else {
2054		/* Get scan command from scan_pending_q and put to
2055		 * cmd_pending_q
2056		 */
2057		cmd_node = list_first_entry(&adapter->scan_pending_q,
2058					    struct cmd_ctrl_node, list);
2059		list_del(&cmd_node->list);
2060		spin_unlock_bh(&adapter->scan_pending_q_lock);
2061		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
2062	}
2063
2064	return;
2065}
2066
2067void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
2068{
2069	struct mwifiex_private *priv;
2070	int i;
2071
2072	mwifiex_cancel_pending_scan_cmd(adapter);
2073
2074	if (adapter->scan_processing) {
2075		spin_lock_bh(&adapter->mwifiex_cmd_lock);
2076		adapter->scan_processing = false;
2077		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
2078		for (i = 0; i < adapter->priv_num; i++) {
2079			priv = adapter->priv[i];
2080			if (!priv)
2081				continue;
2082			if (priv->scan_request) {
2083				struct cfg80211_scan_info info = {
2084					.aborted = true,
2085				};
2086
2087				mwifiex_dbg(adapter, INFO,
2088					    "info: aborting scan\n");
2089				cfg80211_scan_done(priv->scan_request, &info);
2090				priv->scan_request = NULL;
2091				priv->scan_aborting = false;
2092			}
2093		}
2094	}
2095}
2096
2097/*
2098 * This function handles the command response of scan.
2099 *
2100 * The response buffer for the scan command has the following
2101 * memory layout:
2102 *
2103 *      .-------------------------------------------------------------.
2104 *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
2105 *      .-------------------------------------------------------------.
2106 *      |  BufSize (t_u16) : sizeof the BSS Description data          |
2107 *      .-------------------------------------------------------------.
2108 *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
2109 *      .-------------------------------------------------------------.
2110 *      |  BSSDescription data (variable, size given in BufSize)      |
2111 *      .-------------------------------------------------------------.
2112 *      |  TLV data (variable, size calculated using Header->Size,    |
2113 *      |            BufSize and sizeof the fixed fields above)       |
2114 *      .-------------------------------------------------------------.
2115 */
2116int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2117			    struct host_cmd_ds_command *resp)
2118{
2119	int ret = 0;
2120	struct mwifiex_adapter *adapter = priv->adapter;
2121	struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2122	struct mwifiex_ie_types_data *tlv_data;
2123	struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2124	u8 *bss_info;
2125	u32 scan_resp_size;
2126	u32 bytes_left;
2127	u32 idx;
2128	u32 tlv_buf_size;
2129	struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2130	struct chan_band_param_set *chan_band;
2131	u8 is_bgscan_resp;
2132	__le64 fw_tsf = 0;
2133	u8 *radio_type;
2134	struct cfg80211_wowlan_nd_match *pmatch;
2135	struct cfg80211_sched_scan_request *nd_config = NULL;
2136
2137	is_bgscan_resp = (le16_to_cpu(resp->command)
2138			  == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2139	if (is_bgscan_resp)
2140		scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2141	else
2142		scan_rsp = &resp->params.scan_resp;
2143
2144
2145	if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2146		mwifiex_dbg(adapter, ERROR,
2147			    "SCAN_RESP: too many AP returned (%d)\n",
2148			    scan_rsp->number_of_sets);
2149		ret = -1;
2150		goto check_next_scan;
2151	}
2152
2153	/* Check csa channel expiry before parsing scan response */
2154	mwifiex_11h_get_csa_closed_channel(priv);
2155
2156	bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2157	mwifiex_dbg(adapter, INFO,
2158		    "info: SCAN_RESP: bss_descript_size %d\n",
2159		    bytes_left);
2160
2161	scan_resp_size = le16_to_cpu(resp->size);
2162
2163	mwifiex_dbg(adapter, INFO,
2164		    "info: SCAN_RESP: returned %d APs before parsing\n",
2165		    scan_rsp->number_of_sets);
2166
2167	bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2168
2169	/*
2170	 * The size of the TLV buffer is equal to the entire command response
2171	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2172	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
2173	 *   response header (S_DS_GEN)
2174	 */
2175	tlv_buf_size = scan_resp_size - (bytes_left
2176					 + sizeof(scan_rsp->bss_descript_size)
2177					 + sizeof(scan_rsp->number_of_sets)
2178					 + S_DS_GEN);
2179
2180	tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2181						 bss_desc_and_tlv_buffer +
2182						 bytes_left);
2183
2184	/* Search the TLV buffer space in the scan response for any valid
2185	   TLVs */
2186	mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2187					     TLV_TYPE_TSFTIMESTAMP,
2188					     (struct mwifiex_ie_types_data **)
2189					     &tsf_tlv);
2190
2191	/* Search the TLV buffer space in the scan response for any valid
2192	   TLVs */
2193	mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2194					     TLV_TYPE_CHANNELBANDLIST,
2195					     (struct mwifiex_ie_types_data **)
2196					     &chan_band_tlv);
2197
2198#ifdef CONFIG_PM
2199	if (priv->wdev.wiphy->wowlan_config)
2200		nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2201#endif
2202
2203	if (nd_config) {
2204		adapter->nd_info =
2205			kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2206				sizeof(struct cfg80211_wowlan_nd_match *) *
2207				scan_rsp->number_of_sets, GFP_ATOMIC);
2208
2209		if (adapter->nd_info)
2210			adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2211	}
2212
2213	for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2214		/*
2215		 * If the TSF TLV was appended to the scan results, save this
2216		 * entry's TSF value in the fw_tsf field. It is the firmware's
2217		 * TSF value at the time the beacon or probe response was
2218		 * received.
2219		 */
2220		if (tsf_tlv)
2221			memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2222			       sizeof(fw_tsf));
2223
2224		if (chan_band_tlv) {
2225			chan_band = &chan_band_tlv->chan_band_param[idx];
2226			radio_type = &chan_band->radio_type;
2227		} else {
2228			radio_type = NULL;
2229		}
2230
2231		if (chan_band_tlv && adapter->nd_info) {
2232			adapter->nd_info->matches[idx] =
2233				kzalloc(sizeof(*pmatch) + sizeof(u32),
2234					GFP_ATOMIC);
2235
2236			pmatch = adapter->nd_info->matches[idx];
2237
2238			if (pmatch) {
2239				pmatch->n_channels = 1;
2240				pmatch->channels[0] = chan_band->chan_number;
2241			}
2242		}
2243
2244		ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2245							&bytes_left,
2246							le64_to_cpu(fw_tsf),
2247							radio_type, false, 0);
2248		if (ret)
2249			goto check_next_scan;
2250	}
2251
2252check_next_scan:
2253	mwifiex_check_next_scan_command(priv);
2254	return ret;
2255}
2256
2257/*
2258 * This function prepares an extended scan command to be sent to the firmware
2259 *
2260 * This uses the scan command configuration sent to the command processing
2261 * module in command preparation stage to configure a extended scan command
2262 * structure to send to firmware.
2263 */
2264int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2265				struct host_cmd_ds_command *cmd,
2266				void *data_buf)
2267{
2268	struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2269	struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2270
2271	memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2272
2273	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2274
2275	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2276	cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2277				      + scan_cfg->tlv_buf_len + S_DS_GEN));
2278
2279	return 0;
2280}
2281
2282/* This function prepares an background scan config command to be sent
2283 * to the firmware
2284 */
2285int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2286				      struct host_cmd_ds_command *cmd,
2287				      void *data_buf)
2288{
2289	struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2290					&cmd->params.bg_scan_config;
2291	struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2292	u8 *tlv_pos = bgscan_config->tlv;
2293	u8 num_probes;
2294	u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2295	int i;
2296	struct mwifiex_ie_types_num_probes *num_probes_tlv;
2297	struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2298	struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2299	struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2300	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2301	struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2302	struct mwifiex_chan_scan_param_set *temp_chan;
2303
2304	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2305	cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2306
2307	bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2308	bgscan_config->enable = bgscan_cfg_in->enable;
2309	bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2310	bgscan_config->scan_interval =
2311		cpu_to_le32(bgscan_cfg_in->scan_interval);
2312	bgscan_config->report_condition =
2313		cpu_to_le32(bgscan_cfg_in->report_condition);
2314
2315	/*  stop sched scan  */
2316	if (!bgscan_config->enable)
2317		return 0;
2318
2319	bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2320
2321	num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2322		      num_probes : priv->adapter->scan_probes);
2323
2324	if (num_probes) {
2325		num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2326		num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2327		num_probes_tlv->header.len =
2328			cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2329		num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2330
2331		tlv_pos += sizeof(num_probes_tlv->header) +
2332			le16_to_cpu(num_probes_tlv->header.len);
2333	}
2334
2335	if (bgscan_cfg_in->repeat_count) {
2336		repeat_count_tlv =
2337			(struct mwifiex_ie_types_repeat_count *)tlv_pos;
2338		repeat_count_tlv->header.type =
2339			cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2340		repeat_count_tlv->header.len =
2341			cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2342		repeat_count_tlv->repeat_count =
2343			cpu_to_le16(bgscan_cfg_in->repeat_count);
2344
2345		tlv_pos += sizeof(repeat_count_tlv->header) +
2346			le16_to_cpu(repeat_count_tlv->header.len);
2347	}
2348
2349	if (bgscan_cfg_in->rssi_threshold) {
2350		rssi_threshold_tlv =
2351			(struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2352		rssi_threshold_tlv->header.type =
2353			cpu_to_le16(TLV_TYPE_RSSI_LOW);
2354		rssi_threshold_tlv->header.len =
2355			cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2356		rssi_threshold_tlv->rssi_threshold =
2357			cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2358
2359		tlv_pos += sizeof(rssi_threshold_tlv->header) +
2360			le16_to_cpu(rssi_threshold_tlv->header.len);
2361	}
2362
2363	for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2364		ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2365
2366		wildcard_ssid_tlv =
2367			(struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2368		wildcard_ssid_tlv->header.type =
2369				cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2370		wildcard_ssid_tlv->header.len = cpu_to_le16(
2371				(u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2372							 max_ssid_length)));
2373
2374		/* max_ssid_length = 0 tells firmware to perform
2375		 * specific scan for the SSID filled, whereas
2376		 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
2377		 * wildcard scan.
2378		 */
2379		if (ssid_len)
2380			wildcard_ssid_tlv->max_ssid_length = 0;
2381		else
2382			wildcard_ssid_tlv->max_ssid_length =
2383						IEEE80211_MAX_SSID_LEN;
2384
2385		memcpy(wildcard_ssid_tlv->ssid,
2386		       bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2387
2388		tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2389				+ le16_to_cpu(wildcard_ssid_tlv->header.len));
2390	}
2391
2392	chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2393
2394	if (bgscan_cfg_in->chan_list[0].chan_number) {
2395		dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2396
2397		chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2398
2399		for (chan_idx = 0;
2400		     chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2401		     bgscan_cfg_in->chan_list[chan_idx].chan_number;
2402		     chan_idx++) {
2403			temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2404
2405			/* Increment the TLV header length by size appended */
2406			le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2407					       sizeof(
2408					       chan_list_tlv->chan_scan_param));
2409
2410			temp_chan->chan_number =
2411				bgscan_cfg_in->chan_list[chan_idx].chan_number;
2412			temp_chan->radio_type =
2413				bgscan_cfg_in->chan_list[chan_idx].radio_type;
2414
2415			scan_type =
2416				bgscan_cfg_in->chan_list[chan_idx].scan_type;
2417
2418			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2419				temp_chan->chan_scan_mode_bitmap
2420					|= MWIFIEX_PASSIVE_SCAN;
2421			else
2422				temp_chan->chan_scan_mode_bitmap
2423					&= ~MWIFIEX_PASSIVE_SCAN;
2424
2425			if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2426				scan_dur = (u16)bgscan_cfg_in->
2427					chan_list[chan_idx].scan_time;
2428			} else {
2429				scan_dur = (scan_type ==
2430					    MWIFIEX_SCAN_TYPE_PASSIVE) ?
2431					    priv->adapter->passive_scan_time :
2432					    priv->adapter->specific_scan_time;
2433			}
2434
2435			temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2436			temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2437		}
2438	} else {
2439		dev_dbg(priv->adapter->dev,
2440			"info: bgscan: Creating full region channel list\n");
2441		chan_num =
2442			mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2443							   chan_list_tlv->
2444							   chan_scan_param);
2445		le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2446				       chan_num *
2447			     sizeof(chan_list_tlv->chan_scan_param[0]));
2448	}
2449
2450	tlv_pos += (sizeof(chan_list_tlv->header)
2451			+ le16_to_cpu(chan_list_tlv->header.len));
2452
2453	if (bgscan_cfg_in->start_later) {
2454		start_later_tlv =
2455			(struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2456		start_later_tlv->header.type =
2457			cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2458		start_later_tlv->header.len =
2459			cpu_to_le16(sizeof(start_later_tlv->start_later));
2460		start_later_tlv->start_later =
2461			cpu_to_le16(bgscan_cfg_in->start_later);
2462
2463		tlv_pos += sizeof(start_later_tlv->header) +
2464			le16_to_cpu(start_later_tlv->header.len);
2465	}
2466
2467	/* Append vendor specific IE TLV */
2468	mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2469
2470	le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2471
2472	return 0;
2473}
2474
2475int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2476{
2477	struct mwifiex_bg_scan_cfg *bgscan_cfg;
2478
2479	if (!priv->sched_scanning) {
2480		dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2481		return 0;
2482	}
2483
2484	bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2485	if (!bgscan_cfg)
2486		return -ENOMEM;
2487
2488	bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2489	bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2490	bgscan_cfg->enable = false;
2491
2492	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2493			     HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2494		kfree(bgscan_cfg);
2495		return -EFAULT;
2496	}
2497
2498	kfree(bgscan_cfg);
2499	priv->sched_scanning = false;
2500
2501	return 0;
2502}
2503
2504static void
2505mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2506			       struct mwifiex_ietypes_chanstats *tlv_stat)
2507{
2508	struct mwifiex_adapter *adapter = priv->adapter;
2509	u8 i, num_chan;
2510	struct mwifiex_fw_chan_stats *fw_chan_stats;
2511	struct mwifiex_chan_stats chan_stats;
2512
2513	fw_chan_stats = (void *)((u8 *)tlv_stat +
2514			      sizeof(struct mwifiex_ie_types_header));
2515	num_chan = le16_to_cpu(tlv_stat->header.len) /
2516					      sizeof(struct mwifiex_chan_stats);
2517
2518	for (i = 0 ; i < num_chan; i++) {
2519		if (adapter->survey_idx >= adapter->num_in_chan_stats) {
2520			mwifiex_dbg(adapter, WARN,
2521				    "FW reported too many channel results (max %d)\n",
2522				    adapter->num_in_chan_stats);
2523			return;
2524		}
2525		chan_stats.chan_num = fw_chan_stats->chan_num;
2526		chan_stats.bandcfg = fw_chan_stats->bandcfg;
2527		chan_stats.flags = fw_chan_stats->flags;
2528		chan_stats.noise = fw_chan_stats->noise;
2529		chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2530		chan_stats.cca_scan_dur =
2531				       le16_to_cpu(fw_chan_stats->cca_scan_dur);
2532		chan_stats.cca_busy_dur =
2533				       le16_to_cpu(fw_chan_stats->cca_busy_dur);
2534		mwifiex_dbg(adapter, INFO,
2535			    "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2536			    chan_stats.chan_num,
2537			    chan_stats.noise,
2538			    chan_stats.total_bss,
2539			    chan_stats.cca_scan_dur,
2540			    chan_stats.cca_busy_dur);
2541		memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2542		       sizeof(struct mwifiex_chan_stats));
2543		fw_chan_stats++;
2544	}
2545}
2546
2547/* This function handles the command response of extended scan */
2548int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2549				struct host_cmd_ds_command *resp)
2550{
2551	struct mwifiex_adapter *adapter = priv->adapter;
2552	struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2553	struct mwifiex_ie_types_header *tlv;
2554	struct mwifiex_ietypes_chanstats *tlv_stat;
2555	u16 buf_left, type, len;
2556
2557	struct host_cmd_ds_command *cmd_ptr;
2558	struct cmd_ctrl_node *cmd_node;
2559	bool complete_scan = false;
2560
2561	mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2562
2563	ext_scan_resp = &resp->params.ext_scan;
2564
2565	tlv = (void *)ext_scan_resp->tlv_buffer;
2566	buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2567					      - 1);
2568
2569	while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2570		type = le16_to_cpu(tlv->type);
2571		len = le16_to_cpu(tlv->len);
2572
2573		if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2574			mwifiex_dbg(adapter, ERROR,
2575				    "error processing scan response TLVs");
2576			break;
2577		}
2578
2579		switch (type) {
2580		case TLV_TYPE_CHANNEL_STATS:
2581			tlv_stat = (void *)tlv;
2582			mwifiex_update_chan_statistics(priv, tlv_stat);
2583			break;
2584		default:
2585			break;
2586		}
2587
2588		buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2589		tlv = (void *)((u8 *)tlv + len +
2590			       sizeof(struct mwifiex_ie_types_header));
2591	}
2592
2593	spin_lock_bh(&adapter->cmd_pending_q_lock);
2594	spin_lock_bh(&adapter->scan_pending_q_lock);
2595	if (list_empty(&adapter->scan_pending_q)) {
2596		complete_scan = true;
2597		list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2598			cmd_ptr = (void *)cmd_node->cmd_skb->data;
2599			if (le16_to_cpu(cmd_ptr->command) ==
2600			    HostCmd_CMD_802_11_SCAN_EXT) {
2601				mwifiex_dbg(adapter, INFO,
2602					    "Scan pending in command pending list");
2603				complete_scan = false;
2604				break;
2605			}
2606		}
2607	}
2608	spin_unlock_bh(&adapter->scan_pending_q_lock);
2609	spin_unlock_bh(&adapter->cmd_pending_q_lock);
2610
2611	if (complete_scan)
2612		mwifiex_complete_scan(priv);
2613
2614	return 0;
2615}
2616
2617/* This function This function handles the event extended scan report. It
2618 * parses extended scan results and informs to cfg80211 stack.
2619 */
2620int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2621					 void *buf)
2622{
2623	int ret = 0;
2624	struct mwifiex_adapter *adapter = priv->adapter;
2625	u8 *bss_info;
2626	u32 bytes_left, bytes_left_for_tlv, idx;
2627	u16 type, len;
2628	struct mwifiex_ie_types_data *tlv;
2629	struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2630	struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2631	u8 *radio_type;
2632	u64 fw_tsf = 0;
2633	s32 rssi = 0;
2634	struct mwifiex_event_scan_result *event_scan = buf;
2635	u8 num_of_set = event_scan->num_of_set;
2636	u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2637	u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2638
2639	if (num_of_set > MWIFIEX_MAX_AP) {
2640		mwifiex_dbg(adapter, ERROR,
2641			    "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2642			    num_of_set);
2643		ret = -1;
2644		goto check_next_scan;
2645	}
2646
2647	bytes_left = scan_resp_size;
2648	mwifiex_dbg(adapter, INFO,
2649		    "EXT_SCAN: size %d, returned %d APs...",
2650		    scan_resp_size, num_of_set);
2651	mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2652			 scan_resp_size +
2653			 sizeof(struct mwifiex_event_scan_result));
2654
2655	tlv = (struct mwifiex_ie_types_data *)scan_resp;
2656
2657	for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2658		type = le16_to_cpu(tlv->header.type);
2659		len = le16_to_cpu(tlv->header.len);
2660		if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2661			mwifiex_dbg(adapter, ERROR,
2662				    "EXT_SCAN: Error bytes left < TLV length\n");
2663			break;
2664		}
2665		scan_rsp_tlv = NULL;
2666		scan_info_tlv = NULL;
2667		bytes_left_for_tlv = bytes_left;
2668
2669		/* BSS response TLV with beacon or probe response buffer
2670		 * at the initial position of each descriptor
2671		 */
2672		if (type != TLV_TYPE_BSS_SCAN_RSP)
2673			break;
2674
2675		bss_info = (u8 *)tlv;
2676		scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2677		tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2678		bytes_left_for_tlv -=
2679				(len + sizeof(struct mwifiex_ie_types_header));
2680
2681		while (bytes_left_for_tlv >=
2682		       sizeof(struct mwifiex_ie_types_header) &&
2683		       le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2684			type = le16_to_cpu(tlv->header.type);
2685			len = le16_to_cpu(tlv->header.len);
2686			if (bytes_left_for_tlv <
2687			    sizeof(struct mwifiex_ie_types_header) + len) {
2688				mwifiex_dbg(adapter, ERROR,
2689					    "EXT_SCAN: Error in processing TLV,\t"
2690					    "bytes left < TLV length\n");
2691				scan_rsp_tlv = NULL;
2692				bytes_left_for_tlv = 0;
2693				continue;
2694			}
2695			switch (type) {
2696			case TLV_TYPE_BSS_SCAN_INFO:
2697				scan_info_tlv =
2698				  (struct mwifiex_ie_types_bss_scan_info *)tlv;
2699				if (len !=
2700				 sizeof(struct mwifiex_ie_types_bss_scan_info) -
2701				 sizeof(struct mwifiex_ie_types_header)) {
2702					bytes_left_for_tlv = 0;
2703					continue;
2704				}
2705				break;
2706			default:
2707				break;
2708			}
2709			tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2710			bytes_left -=
2711				(len + sizeof(struct mwifiex_ie_types_header));
2712			bytes_left_for_tlv -=
2713				(len + sizeof(struct mwifiex_ie_types_header));
2714		}
2715
2716		if (!scan_rsp_tlv)
2717			break;
2718
2719		/* Advance pointer to the beacon buffer length and
2720		 * update the bytes count so that the function
2721		 * wlan_interpret_bss_desc_with_ie() can handle the
2722		 * scan buffer withut any change
2723		 */
2724		bss_info += sizeof(u16);
2725		bytes_left -= sizeof(u16);
2726
2727		if (scan_info_tlv) {
2728			rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2729			rssi *= 100;           /* Convert dBm to mBm */
2730			mwifiex_dbg(adapter, INFO,
2731				    "info: InterpretIE: RSSI=%d\n", rssi);
2732			fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2733			radio_type = &scan_info_tlv->radio_type;
2734		} else {
2735			radio_type = NULL;
2736		}
2737		ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2738							&bytes_left, fw_tsf,
2739							radio_type, true, rssi);
2740		if (ret)
2741			goto check_next_scan;
2742	}
2743
2744check_next_scan:
2745	if (!event_scan->more_event)
2746		mwifiex_check_next_scan_command(priv);
2747
2748	return ret;
2749}
2750
2751/*
2752 * This function prepares command for background scan query.
2753 *
2754 * Preparation includes -
2755 *      - Setting command ID and proper size
2756 *      - Setting background scan flush parameter
2757 *      - Ensuring correct endian-ness
2758 */
2759int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2760{
2761	struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2762		&cmd->params.bg_scan_query;
2763
2764	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2765	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2766				+ S_DS_GEN);
2767
2768	bg_query->flush = 1;
2769
2770	return 0;
2771}
2772
2773/*
2774 * This function inserts scan command node to the scan pending queue.
2775 */
2776void
2777mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2778		       struct cmd_ctrl_node *cmd_node)
2779{
2780	struct mwifiex_adapter *adapter = priv->adapter;
2781
2782	cmd_node->wait_q_enabled = true;
2783	cmd_node->condition = &adapter->scan_wait_q_woken;
2784	spin_lock_bh(&adapter->scan_pending_q_lock);
2785	list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2786	spin_unlock_bh(&adapter->scan_pending_q_lock);
2787}
2788
2789/*
2790 * This function sends a scan command for all available channels to the
2791 * firmware, filtered on a specific SSID.
2792 */
2793static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2794				      struct cfg80211_ssid *req_ssid)
2795{
2796	struct mwifiex_adapter *adapter = priv->adapter;
2797	int ret;
2798	struct mwifiex_user_scan_cfg *scan_cfg;
2799
2800	if (adapter->scan_processing) {
2801		mwifiex_dbg(adapter, WARN,
2802			    "cmd: Scan already in process...\n");
2803		return -EBUSY;
2804	}
2805
2806	if (priv->scan_block) {
2807		mwifiex_dbg(adapter, WARN,
2808			    "cmd: Scan is blocked during association...\n");
2809		return -EBUSY;
2810	}
2811
2812	scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2813	if (!scan_cfg)
2814		return -ENOMEM;
2815
2816	scan_cfg->ssid_list = req_ssid;
2817	scan_cfg->num_ssids = 1;
2818
2819	ret = mwifiex_scan_networks(priv, scan_cfg);
2820
2821	kfree(scan_cfg);
2822	return ret;
2823}
2824
2825/*
2826 * Sends IOCTL request to start a scan.
2827 *
2828 * This function allocates the IOCTL request buffer, fills it
2829 * with requisite parameters and calls the IOCTL handler.
2830 *
2831 * Scan command can be issued for both normal scan and specific SSID
2832 * scan, depending upon whether an SSID is provided or not.
2833 */
2834int mwifiex_request_scan(struct mwifiex_private *priv,
2835			 struct cfg80211_ssid *req_ssid)
2836{
2837	int ret;
2838
2839	if (mutex_lock_interruptible(&priv->async_mutex)) {
2840		mwifiex_dbg(priv->adapter, ERROR,
2841			    "%s: acquire semaphore fail\n",
2842			    __func__);
2843		return -1;
2844	}
2845
2846	priv->adapter->scan_wait_q_woken = false;
2847
2848	if (req_ssid && req_ssid->ssid_len != 0)
2849		/* Specific SSID scan */
2850		ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2851	else
2852		/* Normal scan */
2853		ret = mwifiex_scan_networks(priv, NULL);
2854
2855	mutex_unlock(&priv->async_mutex);
2856
2857	return ret;
2858}
2859
2860/*
2861 * This function appends the vendor specific IE TLV to a buffer.
2862 */
2863int
2864mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2865			    u16 vsie_mask, u8 **buffer)
2866{
2867	int id, ret_len = 0;
2868	struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2869
2870	if (!buffer)
2871		return 0;
2872	if (!(*buffer))
2873		return 0;
2874
2875	/*
2876	 * Traverse through the saved vendor specific IE array and append
2877	 * the selected(scan/assoc/adhoc) IE as TLV to the command
2878	 */
2879	for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2880		if (priv->vs_ie[id].mask & vsie_mask) {
2881			vs_param_set =
2882				(struct mwifiex_ie_types_vendor_param_set *)
2883				*buffer;
2884			vs_param_set->header.type =
2885				cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2886			vs_param_set->header.len =
2887				cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2888				& 0x00FF) + 2);
2889			memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2890			       le16_to_cpu(vs_param_set->header.len));
2891			*buffer += le16_to_cpu(vs_param_set->header.len) +
2892				   sizeof(struct mwifiex_ie_types_header);
2893			ret_len += le16_to_cpu(vs_param_set->header.len) +
2894				   sizeof(struct mwifiex_ie_types_header);
2895		}
2896	}
2897	return ret_len;
2898}
2899
2900/*
2901 * This function saves a beacon buffer of the current BSS descriptor.
2902 *
2903 * The current beacon buffer is saved so that it can be restored in the
2904 * following cases that makes the beacon buffer not to contain the current
2905 * ssid's beacon buffer.
2906 *      - The current ssid was not found somehow in the last scan.
2907 *      - The current ssid was the last entry of the scan table and overloaded.
2908 */
2909void
2910mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2911{
2912	struct mwifiex_bssdescriptor *curr_bss =
2913		&priv->curr_bss_params.bss_descriptor;
2914
2915	if (!curr_bss->beacon_buf_size)
2916		return;
2917
2918	/* allocate beacon buffer at 1st time; or if it's size has changed */
2919	if (!priv->curr_bcn_buf ||
2920	    priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2921		priv->curr_bcn_size = curr_bss->beacon_buf_size;
2922
2923		kfree(priv->curr_bcn_buf);
2924		priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2925					     GFP_ATOMIC);
2926		if (!priv->curr_bcn_buf)
2927			return;
2928	}
2929
2930	memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2931	       curr_bss->beacon_buf_size);
2932	mwifiex_dbg(priv->adapter, INFO,
2933		    "info: current beacon saved %d\n",
2934		    priv->curr_bcn_size);
2935
2936	curr_bss->beacon_buf = priv->curr_bcn_buf;
2937
2938	/* adjust the pointers in the current BSS descriptor */
2939	if (curr_bss->bcn_wpa_ie)
2940		curr_bss->bcn_wpa_ie =
2941			(struct ieee_types_vendor_specific *)
2942			(curr_bss->beacon_buf +
2943			 curr_bss->wpa_offset);
2944
2945	if (curr_bss->bcn_rsn_ie)
2946		curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2947			(curr_bss->beacon_buf +
2948			 curr_bss->rsn_offset);
2949
2950	if (curr_bss->bcn_ht_cap)
2951		curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2952			(curr_bss->beacon_buf +
2953			 curr_bss->ht_cap_offset);
2954
2955	if (curr_bss->bcn_ht_oper)
2956		curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2957			(curr_bss->beacon_buf +
2958			 curr_bss->ht_info_offset);
2959
2960	if (curr_bss->bcn_vht_cap)
2961		curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2962						 curr_bss->vht_cap_offset);
2963
2964	if (curr_bss->bcn_vht_oper)
2965		curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2966						  curr_bss->vht_info_offset);
2967
2968	if (curr_bss->bcn_bss_co_2040)
2969		curr_bss->bcn_bss_co_2040 =
2970			(curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2971
2972	if (curr_bss->bcn_ext_cap)
2973		curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2974			curr_bss->ext_cap_offset;
2975
2976	if (curr_bss->oper_mode)
2977		curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2978					       curr_bss->oper_mode_offset);
2979}
2980
2981/*
2982 * This function frees the current BSS descriptor beacon buffer.
2983 */
2984void
2985mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2986{
2987	kfree(priv->curr_bcn_buf);
2988	priv->curr_bcn_buf = NULL;
2989}