Linux Audio

Check our new training course

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