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