linux/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010 Broadcom Corporation
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
  18
  19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  20
  21#include <linux/kernel.h>
  22#include <linux/etherdevice.h>
  23#include <net/cfg80211.h>
  24#include <net/netlink.h>
  25
  26#include <brcmu_utils.h>
  27#include <defs.h>
  28#include <brcmu_wifi.h>
  29#include "dhd.h"
  30#include "dhd_dbg.h"
  31#include "wl_cfg80211.h"
  32#include "fwil.h"
  33
  34#define BRCMF_SCAN_IE_LEN_MAX           2048
  35#define BRCMF_PNO_VERSION               2
  36#define BRCMF_PNO_TIME                  30
  37#define BRCMF_PNO_REPEAT                4
  38#define BRCMF_PNO_FREQ_EXPO_MAX         3
  39#define BRCMF_PNO_MAX_PFN_COUNT         16
  40#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT  6
  41#define BRCMF_PNO_HIDDEN_BIT            2
  42#define BRCMF_PNO_WPA_AUTH_ANY          0xFFFFFFFF
  43#define BRCMF_PNO_SCAN_COMPLETE         1
  44#define BRCMF_PNO_SCAN_INCOMPLETE       0
  45
  46#define BRCMF_IFACE_MAX_CNT             2
  47
  48#define TLV_LEN_OFF                     1       /* length offset */
  49#define TLV_HDR_LEN                     2       /* header length */
  50#define TLV_BODY_OFF                    2       /* body offset */
  51#define TLV_OUI_LEN                     3       /* oui id length */
  52#define WPA_OUI                         "\x00\x50\xF2"  /* WPA OUI */
  53#define WPA_OUI_TYPE                    1
  54#define RSN_OUI                         "\x00\x0F\xAC"  /* RSN OUI */
  55#define WME_OUI_TYPE                    2
  56
  57#define VS_IE_FIXED_HDR_LEN             6
  58#define WPA_IE_VERSION_LEN              2
  59#define WPA_IE_MIN_OUI_LEN              4
  60#define WPA_IE_SUITE_COUNT_LEN          2
  61
  62#define WPA_CIPHER_NONE                 0       /* None */
  63#define WPA_CIPHER_WEP_40               1       /* WEP (40-bit) */
  64#define WPA_CIPHER_TKIP                 2       /* TKIP: default for WPA */
  65#define WPA_CIPHER_AES_CCM              4       /* AES (CCM) */
  66#define WPA_CIPHER_WEP_104              5       /* WEP (104-bit) */
  67
  68#define RSN_AKM_NONE                    0       /* None (IBSS) */
  69#define RSN_AKM_UNSPECIFIED             1       /* Over 802.1x */
  70#define RSN_AKM_PSK                     2       /* Pre-shared Key */
  71#define RSN_CAP_LEN                     2       /* Length of RSN capabilities */
  72#define RSN_CAP_PTK_REPLAY_CNTR_MASK    0x000C
  73
  74#define VNDR_IE_CMD_LEN                 4       /* length of the set command
  75                                                 * string :"add", "del" (+ NUL)
  76                                                 */
  77#define VNDR_IE_COUNT_OFFSET            4
  78#define VNDR_IE_PKTFLAG_OFFSET          8
  79#define VNDR_IE_VSIE_OFFSET             12
  80#define VNDR_IE_HDR_SIZE                12
  81#define VNDR_IE_BEACON_FLAG             0x1
  82#define VNDR_IE_PRBRSP_FLAG             0x2
  83#define MAX_VNDR_IE_NUMBER              5
  84
  85#define DOT11_MGMT_HDR_LEN              24      /* d11 management header len */
  86#define DOT11_BCN_PRB_FIXED_LEN         12      /* beacon/probe fixed length */
  87
  88#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
  89        (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
  90
  91static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
  92{
  93        if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
  94                brcmf_dbg(INFO, "device is not ready : status (%lu)\n",
  95                          vif->sme_state);
  96                return false;
  97        }
  98        return true;
  99}
 100
 101#define CHAN2G(_channel, _freq, _flags) {                       \
 102        .band                   = IEEE80211_BAND_2GHZ,          \
 103        .center_freq            = (_freq),                      \
 104        .hw_value               = (_channel),                   \
 105        .flags                  = (_flags),                     \
 106        .max_antenna_gain       = 0,                            \
 107        .max_power              = 30,                           \
 108}
 109
 110#define CHAN5G(_channel, _flags) {                              \
 111        .band                   = IEEE80211_BAND_5GHZ,          \
 112        .center_freq            = 5000 + (5 * (_channel)),      \
 113        .hw_value               = (_channel),                   \
 114        .flags                  = (_flags),                     \
 115        .max_antenna_gain       = 0,                            \
 116        .max_power              = 30,                           \
 117}
 118
 119#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
 120#define RATETAB_ENT(_rateid, _flags) \
 121        {                                                               \
 122                .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
 123                .hw_value       = (_rateid),                            \
 124                .flags          = (_flags),                             \
 125        }
 126
 127static struct ieee80211_rate __wl_rates[] = {
 128        RATETAB_ENT(BRCM_RATE_1M, 0),
 129        RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
 130        RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
 131        RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
 132        RATETAB_ENT(BRCM_RATE_6M, 0),
 133        RATETAB_ENT(BRCM_RATE_9M, 0),
 134        RATETAB_ENT(BRCM_RATE_12M, 0),
 135        RATETAB_ENT(BRCM_RATE_18M, 0),
 136        RATETAB_ENT(BRCM_RATE_24M, 0),
 137        RATETAB_ENT(BRCM_RATE_36M, 0),
 138        RATETAB_ENT(BRCM_RATE_48M, 0),
 139        RATETAB_ENT(BRCM_RATE_54M, 0),
 140};
 141
 142#define wl_a_rates              (__wl_rates + 4)
 143#define wl_a_rates_size 8
 144#define wl_g_rates              (__wl_rates + 0)
 145#define wl_g_rates_size 12
 146
 147static struct ieee80211_channel __wl_2ghz_channels[] = {
 148        CHAN2G(1, 2412, 0),
 149        CHAN2G(2, 2417, 0),
 150        CHAN2G(3, 2422, 0),
 151        CHAN2G(4, 2427, 0),
 152        CHAN2G(5, 2432, 0),
 153        CHAN2G(6, 2437, 0),
 154        CHAN2G(7, 2442, 0),
 155        CHAN2G(8, 2447, 0),
 156        CHAN2G(9, 2452, 0),
 157        CHAN2G(10, 2457, 0),
 158        CHAN2G(11, 2462, 0),
 159        CHAN2G(12, 2467, 0),
 160        CHAN2G(13, 2472, 0),
 161        CHAN2G(14, 2484, 0),
 162};
 163
 164static struct ieee80211_channel __wl_5ghz_a_channels[] = {
 165        CHAN5G(34, 0), CHAN5G(36, 0),
 166        CHAN5G(38, 0), CHAN5G(40, 0),
 167        CHAN5G(42, 0), CHAN5G(44, 0),
 168        CHAN5G(46, 0), CHAN5G(48, 0),
 169        CHAN5G(52, 0), CHAN5G(56, 0),
 170        CHAN5G(60, 0), CHAN5G(64, 0),
 171        CHAN5G(100, 0), CHAN5G(104, 0),
 172        CHAN5G(108, 0), CHAN5G(112, 0),
 173        CHAN5G(116, 0), CHAN5G(120, 0),
 174        CHAN5G(124, 0), CHAN5G(128, 0),
 175        CHAN5G(132, 0), CHAN5G(136, 0),
 176        CHAN5G(140, 0), CHAN5G(149, 0),
 177        CHAN5G(153, 0), CHAN5G(157, 0),
 178        CHAN5G(161, 0), CHAN5G(165, 0),
 179        CHAN5G(184, 0), CHAN5G(188, 0),
 180        CHAN5G(192, 0), CHAN5G(196, 0),
 181        CHAN5G(200, 0), CHAN5G(204, 0),
 182        CHAN5G(208, 0), CHAN5G(212, 0),
 183        CHAN5G(216, 0),
 184};
 185
 186static struct ieee80211_channel __wl_5ghz_n_channels[] = {
 187        CHAN5G(32, 0), CHAN5G(34, 0),
 188        CHAN5G(36, 0), CHAN5G(38, 0),
 189        CHAN5G(40, 0), CHAN5G(42, 0),
 190        CHAN5G(44, 0), CHAN5G(46, 0),
 191        CHAN5G(48, 0), CHAN5G(50, 0),
 192        CHAN5G(52, 0), CHAN5G(54, 0),
 193        CHAN5G(56, 0), CHAN5G(58, 0),
 194        CHAN5G(60, 0), CHAN5G(62, 0),
 195        CHAN5G(64, 0), CHAN5G(66, 0),
 196        CHAN5G(68, 0), CHAN5G(70, 0),
 197        CHAN5G(72, 0), CHAN5G(74, 0),
 198        CHAN5G(76, 0), CHAN5G(78, 0),
 199        CHAN5G(80, 0), CHAN5G(82, 0),
 200        CHAN5G(84, 0), CHAN5G(86, 0),
 201        CHAN5G(88, 0), CHAN5G(90, 0),
 202        CHAN5G(92, 0), CHAN5G(94, 0),
 203        CHAN5G(96, 0), CHAN5G(98, 0),
 204        CHAN5G(100, 0), CHAN5G(102, 0),
 205        CHAN5G(104, 0), CHAN5G(106, 0),
 206        CHAN5G(108, 0), CHAN5G(110, 0),
 207        CHAN5G(112, 0), CHAN5G(114, 0),
 208        CHAN5G(116, 0), CHAN5G(118, 0),
 209        CHAN5G(120, 0), CHAN5G(122, 0),
 210        CHAN5G(124, 0), CHAN5G(126, 0),
 211        CHAN5G(128, 0), CHAN5G(130, 0),
 212        CHAN5G(132, 0), CHAN5G(134, 0),
 213        CHAN5G(136, 0), CHAN5G(138, 0),
 214        CHAN5G(140, 0), CHAN5G(142, 0),
 215        CHAN5G(144, 0), CHAN5G(145, 0),
 216        CHAN5G(146, 0), CHAN5G(147, 0),
 217        CHAN5G(148, 0), CHAN5G(149, 0),
 218        CHAN5G(150, 0), CHAN5G(151, 0),
 219        CHAN5G(152, 0), CHAN5G(153, 0),
 220        CHAN5G(154, 0), CHAN5G(155, 0),
 221        CHAN5G(156, 0), CHAN5G(157, 0),
 222        CHAN5G(158, 0), CHAN5G(159, 0),
 223        CHAN5G(160, 0), CHAN5G(161, 0),
 224        CHAN5G(162, 0), CHAN5G(163, 0),
 225        CHAN5G(164, 0), CHAN5G(165, 0),
 226        CHAN5G(166, 0), CHAN5G(168, 0),
 227        CHAN5G(170, 0), CHAN5G(172, 0),
 228        CHAN5G(174, 0), CHAN5G(176, 0),
 229        CHAN5G(178, 0), CHAN5G(180, 0),
 230        CHAN5G(182, 0), CHAN5G(184, 0),
 231        CHAN5G(186, 0), CHAN5G(188, 0),
 232        CHAN5G(190, 0), CHAN5G(192, 0),
 233        CHAN5G(194, 0), CHAN5G(196, 0),
 234        CHAN5G(198, 0), CHAN5G(200, 0),
 235        CHAN5G(202, 0), CHAN5G(204, 0),
 236        CHAN5G(206, 0), CHAN5G(208, 0),
 237        CHAN5G(210, 0), CHAN5G(212, 0),
 238        CHAN5G(214, 0), CHAN5G(216, 0),
 239        CHAN5G(218, 0), CHAN5G(220, 0),
 240        CHAN5G(222, 0), CHAN5G(224, 0),
 241        CHAN5G(226, 0), CHAN5G(228, 0),
 242};
 243
 244static struct ieee80211_supported_band __wl_band_2ghz = {
 245        .band = IEEE80211_BAND_2GHZ,
 246        .channels = __wl_2ghz_channels,
 247        .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
 248        .bitrates = wl_g_rates,
 249        .n_bitrates = wl_g_rates_size,
 250};
 251
 252static struct ieee80211_supported_band __wl_band_5ghz_a = {
 253        .band = IEEE80211_BAND_5GHZ,
 254        .channels = __wl_5ghz_a_channels,
 255        .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
 256        .bitrates = wl_a_rates,
 257        .n_bitrates = wl_a_rates_size,
 258};
 259
 260static struct ieee80211_supported_band __wl_band_5ghz_n = {
 261        .band = IEEE80211_BAND_5GHZ,
 262        .channels = __wl_5ghz_n_channels,
 263        .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
 264        .bitrates = wl_a_rates,
 265        .n_bitrates = wl_a_rates_size,
 266};
 267
 268static const u32 __wl_cipher_suites[] = {
 269        WLAN_CIPHER_SUITE_WEP40,
 270        WLAN_CIPHER_SUITE_WEP104,
 271        WLAN_CIPHER_SUITE_TKIP,
 272        WLAN_CIPHER_SUITE_CCMP,
 273        WLAN_CIPHER_SUITE_AES_CMAC,
 274};
 275
 276/* tag_ID/length/value_buffer tuple */
 277struct brcmf_tlv {
 278        u8 id;
 279        u8 len;
 280        u8 data[1];
 281};
 282
 283/* Vendor specific ie. id = 221, oui and type defines exact ie */
 284struct brcmf_vs_tlv {
 285        u8 id;
 286        u8 len;
 287        u8 oui[3];
 288        u8 oui_type;
 289};
 290
 291struct parsed_vndr_ie_info {
 292        u8 *ie_ptr;
 293        u32 ie_len;     /* total length including id & length field */
 294        struct brcmf_vs_tlv vndrie;
 295};
 296
 297struct parsed_vndr_ies {
 298        u32 count;
 299        struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER];
 300};
 301
 302/* Quarter dBm units to mW
 303 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
 304 * Table is offset so the last entry is largest mW value that fits in
 305 * a u16.
 306 */
 307
 308#define QDBM_OFFSET 153         /* Offset for first entry */
 309#define QDBM_TABLE_LEN 40       /* Table size */
 310
 311/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
 312 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
 313 */
 314#define QDBM_TABLE_LOW_BOUND 6493       /* Low bound */
 315
 316/* Largest mW value that will round down to the last table entry,
 317 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
 318 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
 319 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
 320 */
 321#define QDBM_TABLE_HIGH_BOUND 64938     /* High bound */
 322
 323static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
 324/* qdBm:        +0      +1      +2      +3      +4      +5      +6      +7 */
 325/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
 326/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
 327/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
 328/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
 329/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
 330};
 331
 332static u16 brcmf_qdbm_to_mw(u8 qdbm)
 333{
 334        uint factor = 1;
 335        int idx = qdbm - QDBM_OFFSET;
 336
 337        if (idx >= QDBM_TABLE_LEN)
 338                /* clamp to max u16 mW value */
 339                return 0xFFFF;
 340
 341        /* scale the qdBm index up to the range of the table 0-40
 342         * where an offset of 40 qdBm equals a factor of 10 mW.
 343         */
 344        while (idx < 0) {
 345                idx += 40;
 346                factor *= 10;
 347        }
 348
 349        /* return the mW value scaled down to the correct factor of 10,
 350         * adding in factor/2 to get proper rounding.
 351         */
 352        return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
 353}
 354
 355static u8 brcmf_mw_to_qdbm(u16 mw)
 356{
 357        u8 qdbm;
 358        int offset;
 359        uint mw_uint = mw;
 360        uint boundary;
 361
 362        /* handle boundary case */
 363        if (mw_uint <= 1)
 364                return 0;
 365
 366        offset = QDBM_OFFSET;
 367
 368        /* move mw into the range of the table */
 369        while (mw_uint < QDBM_TABLE_LOW_BOUND) {
 370                mw_uint *= 10;
 371                offset -= 40;
 372        }
 373
 374        for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
 375                boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
 376                                                    nqdBm_to_mW_map[qdbm]) / 2;
 377                if (mw_uint < boundary)
 378                        break;
 379        }
 380
 381        qdbm += (u8) offset;
 382
 383        return qdbm;
 384}
 385
 386static u16 channel_to_chanspec(struct ieee80211_channel *ch)
 387{
 388        u16 chanspec;
 389
 390        chanspec = ieee80211_frequency_to_channel(ch->center_freq);
 391        chanspec &= WL_CHANSPEC_CHAN_MASK;
 392
 393        if (ch->band == IEEE80211_BAND_2GHZ)
 394                chanspec |= WL_CHANSPEC_BAND_2G;
 395        else
 396                chanspec |= WL_CHANSPEC_BAND_5G;
 397
 398        if (ch->flags & IEEE80211_CHAN_NO_HT40) {
 399                chanspec |= WL_CHANSPEC_BW_20;
 400                chanspec |= WL_CHANSPEC_CTL_SB_NONE;
 401        } else {
 402                chanspec |= WL_CHANSPEC_BW_40;
 403                if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS)
 404                        chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
 405                else
 406                        chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
 407        }
 408        return chanspec;
 409}
 410
 411static void convert_key_from_CPU(struct brcmf_wsec_key *key,
 412                                 struct brcmf_wsec_key_le *key_le)
 413{
 414        key_le->index = cpu_to_le32(key->index);
 415        key_le->len = cpu_to_le32(key->len);
 416        key_le->algo = cpu_to_le32(key->algo);
 417        key_le->flags = cpu_to_le32(key->flags);
 418        key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
 419        key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
 420        key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
 421        memcpy(key_le->data, key->data, sizeof(key->data));
 422        memcpy(key_le->ea, key->ea, sizeof(key->ea));
 423}
 424
 425static int
 426send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
 427{
 428        int err;
 429        struct brcmf_wsec_key_le key_le;
 430
 431        convert_key_from_CPU(key, &key_le);
 432
 433        brcmf_netdev_wait_pend8021x(ndev);
 434
 435        err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
 436                                        sizeof(key_le));
 437
 438        if (err)
 439                brcmf_err("wsec_key error (%d)\n", err);
 440        return err;
 441}
 442
 443static s32
 444brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 445                         enum nl80211_iftype type, u32 *flags,
 446                         struct vif_params *params)
 447{
 448        struct brcmf_if *ifp = netdev_priv(ndev);
 449        struct brcmf_cfg80211_vif *vif = ifp->vif;
 450        s32 infra = 0;
 451        s32 ap = 0;
 452        s32 err = 0;
 453
 454        brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
 455
 456        switch (type) {
 457        case NL80211_IFTYPE_MONITOR:
 458        case NL80211_IFTYPE_WDS:
 459                brcmf_err("type (%d) : currently we do not support this type\n",
 460                          type);
 461                return -EOPNOTSUPP;
 462        case NL80211_IFTYPE_ADHOC:
 463                vif->mode = WL_MODE_IBSS;
 464                infra = 0;
 465                break;
 466        case NL80211_IFTYPE_STATION:
 467                vif->mode = WL_MODE_BSS;
 468                infra = 1;
 469                break;
 470        case NL80211_IFTYPE_AP:
 471                vif->mode = WL_MODE_AP;
 472                ap = 1;
 473                break;
 474        default:
 475                err = -EINVAL;
 476                goto done;
 477        }
 478
 479        if (ap) {
 480                set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state);
 481                brcmf_dbg(INFO, "IF Type = AP\n");
 482        } else {
 483                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra);
 484                if (err) {
 485                        brcmf_err("WLC_SET_INFRA error (%d)\n", err);
 486                        err = -EAGAIN;
 487                        goto done;
 488                }
 489                brcmf_dbg(INFO, "IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ?
 490                          "Adhoc" : "Infra");
 491        }
 492        ndev->ieee80211_ptr->iftype = type;
 493
 494done:
 495        brcmf_dbg(TRACE, "Exit\n");
 496
 497        return err;
 498}
 499
 500static void brcmf_set_mpc(struct net_device *ndev, int mpc)
 501{
 502        struct brcmf_if *ifp = netdev_priv(ndev);
 503        s32 err = 0;
 504
 505        if (check_vif_up(ifp->vif)) {
 506                err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
 507                if (err) {
 508                        brcmf_err("fail to set mpc\n");
 509                        return;
 510                }
 511                brcmf_dbg(INFO, "MPC : %d\n", mpc);
 512        }
 513}
 514
 515static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
 516                             struct cfg80211_scan_request *request)
 517{
 518        u32 n_ssids;
 519        u32 n_channels;
 520        s32 i;
 521        s32 offset;
 522        u16 chanspec;
 523        char *ptr;
 524        struct brcmf_ssid_le ssid_le;
 525
 526        memset(params_le->bssid, 0xFF, ETH_ALEN);
 527        params_le->bss_type = DOT11_BSSTYPE_ANY;
 528        params_le->scan_type = 0;
 529        params_le->channel_num = 0;
 530        params_le->nprobes = cpu_to_le32(-1);
 531        params_le->active_time = cpu_to_le32(-1);
 532        params_le->passive_time = cpu_to_le32(-1);
 533        params_le->home_time = cpu_to_le32(-1);
 534        memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
 535
 536        /* if request is null exit so it will be all channel broadcast scan */
 537        if (!request)
 538                return;
 539
 540        n_ssids = request->n_ssids;
 541        n_channels = request->n_channels;
 542        /* Copy channel array if applicable */
 543        brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
 544                  n_channels);
 545        if (n_channels > 0) {
 546                for (i = 0; i < n_channels; i++) {
 547                        chanspec = channel_to_chanspec(request->channels[i]);
 548                        brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
 549                                  request->channels[i]->hw_value, chanspec);
 550                        params_le->channel_list[i] = cpu_to_le16(chanspec);
 551                }
 552        } else {
 553                brcmf_dbg(SCAN, "Scanning all channels\n");
 554        }
 555        /* Copy ssid array if applicable */
 556        brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
 557        if (n_ssids > 0) {
 558                offset = offsetof(struct brcmf_scan_params_le, channel_list) +
 559                                n_channels * sizeof(u16);
 560                offset = roundup(offset, sizeof(u32));
 561                ptr = (char *)params_le + offset;
 562                for (i = 0; i < n_ssids; i++) {
 563                        memset(&ssid_le, 0, sizeof(ssid_le));
 564                        ssid_le.SSID_len =
 565                                        cpu_to_le32(request->ssids[i].ssid_len);
 566                        memcpy(ssid_le.SSID, request->ssids[i].ssid,
 567                               request->ssids[i].ssid_len);
 568                        if (!ssid_le.SSID_len)
 569                                brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
 570                        else
 571                                brcmf_dbg(SCAN, "%d: scan for  %s size =%d\n",
 572                                          i, ssid_le.SSID, ssid_le.SSID_len);
 573                        memcpy(ptr, &ssid_le, sizeof(ssid_le));
 574                        ptr += sizeof(ssid_le);
 575                }
 576        } else {
 577                brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids);
 578                if ((request->ssids) && request->ssids->ssid_len) {
 579                        brcmf_dbg(SCAN, "SSID %s len=%d\n",
 580                                  params_le->ssid_le.SSID,
 581                                  request->ssids->ssid_len);
 582                        params_le->ssid_le.SSID_len =
 583                                cpu_to_le32(request->ssids->ssid_len);
 584                        memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
 585                                request->ssids->ssid_len);
 586                }
 587        }
 588        /* Adding mask to channel numbers */
 589        params_le->channel_num =
 590                cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
 591                        (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
 592}
 593
 594static s32
 595brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 596                            struct net_device *ndev,
 597                            bool aborted, bool fw_abort)
 598{
 599        struct brcmf_scan_params_le params_le;
 600        struct cfg80211_scan_request *scan_request;
 601        s32 err = 0;
 602
 603        brcmf_dbg(SCAN, "Enter\n");
 604
 605        /* clear scan request, because the FW abort can cause a second call */
 606        /* to this functon and might cause a double cfg80211_scan_done      */
 607        scan_request = cfg->scan_request;
 608        cfg->scan_request = NULL;
 609
 610        if (timer_pending(&cfg->escan_timeout))
 611                del_timer_sync(&cfg->escan_timeout);
 612
 613        if (fw_abort) {
 614                /* Do a scan abort to stop the driver's scan engine */
 615                brcmf_dbg(SCAN, "ABORT scan in firmware\n");
 616                memset(&params_le, 0, sizeof(params_le));
 617                memset(params_le.bssid, 0xFF, ETH_ALEN);
 618                params_le.bss_type = DOT11_BSSTYPE_ANY;
 619                params_le.scan_type = 0;
 620                params_le.channel_num = cpu_to_le32(1);
 621                params_le.nprobes = cpu_to_le32(1);
 622                params_le.active_time = cpu_to_le32(-1);
 623                params_le.passive_time = cpu_to_le32(-1);
 624                params_le.home_time = cpu_to_le32(-1);
 625                /* Scan is aborted by setting channel_list[0] to -1 */
 626                params_le.channel_list[0] = cpu_to_le16(-1);
 627                /* E-Scan (or anyother type) can be aborted by SCAN */
 628                err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
 629                                             &params_le, sizeof(params_le));
 630                if (err)
 631                        brcmf_err("Scan abort  failed\n");
 632        }
 633        /*
 634         * e-scan can be initiated by scheduled scan
 635         * which takes precedence.
 636         */
 637        if (cfg->sched_escan) {
 638                brcmf_dbg(SCAN, "scheduled scan completed\n");
 639                cfg->sched_escan = false;
 640                if (!aborted)
 641                        cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
 642                brcmf_set_mpc(ndev, 1);
 643        } else if (scan_request) {
 644                brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
 645                          aborted ? "Aborted" : "Done");
 646                cfg80211_scan_done(scan_request, aborted);
 647                brcmf_set_mpc(ndev, 1);
 648        }
 649        if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
 650                brcmf_err("Scan complete while device not scanning\n");
 651                return -EPERM;
 652        }
 653
 654        return err;
 655}
 656
 657static s32
 658brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
 659                struct cfg80211_scan_request *request, u16 action)
 660{
 661        s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
 662                          offsetof(struct brcmf_escan_params_le, params_le);
 663        struct brcmf_escan_params_le *params;
 664        s32 err = 0;
 665
 666        brcmf_dbg(SCAN, "E-SCAN START\n");
 667
 668        if (request != NULL) {
 669                /* Allocate space for populating ssids in struct */
 670                params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
 671
 672                /* Allocate space for populating ssids in struct */
 673                params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
 674        }
 675
 676        params = kzalloc(params_size, GFP_KERNEL);
 677        if (!params) {
 678                err = -ENOMEM;
 679                goto exit;
 680        }
 681        BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
 682        brcmf_escan_prep(&params->params_le, request);
 683        params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
 684        params->action = cpu_to_le16(action);
 685        params->sync_id = cpu_to_le16(0x1234);
 686
 687        err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
 688                                       params, params_size);
 689        if (err) {
 690                if (err == -EBUSY)
 691                        brcmf_dbg(INFO, "system busy : escan canceled\n");
 692                else
 693                        brcmf_err("error (%d)\n", err);
 694        }
 695
 696        kfree(params);
 697exit:
 698        return err;
 699}
 700
 701static s32
 702brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
 703               struct net_device *ndev, struct cfg80211_scan_request *request)
 704{
 705        s32 err;
 706        u32 passive_scan;
 707        struct brcmf_scan_results *results;
 708
 709        brcmf_dbg(SCAN, "Enter\n");
 710        cfg->escan_info.ndev = ndev;
 711        cfg->escan_info.wiphy = wiphy;
 712        cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
 713        passive_scan = cfg->active_scan ? 0 : 1;
 714        err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN,
 715                                    passive_scan);
 716        if (err) {
 717                brcmf_err("error (%d)\n", err);
 718                return err;
 719        }
 720        brcmf_set_mpc(ndev, 0);
 721        results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
 722        results->version = 0;
 723        results->count = 0;
 724        results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
 725
 726        err = brcmf_run_escan(cfg, ndev, request, WL_ESCAN_ACTION_START);
 727        if (err)
 728                brcmf_set_mpc(ndev, 1);
 729        return err;
 730}
 731
 732static s32
 733brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
 734                     struct cfg80211_scan_request *request,
 735                     struct cfg80211_ssid *this_ssid)
 736{
 737        struct brcmf_if *ifp = netdev_priv(ndev);
 738        struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
 739        struct cfg80211_ssid *ssids;
 740        struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
 741        u32 passive_scan;
 742        bool escan_req;
 743        bool spec_scan;
 744        s32 err;
 745        u32 SSID_len;
 746
 747        brcmf_dbg(SCAN, "START ESCAN\n");
 748
 749        if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
 750                brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
 751                return -EAGAIN;
 752        }
 753        if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
 754                brcmf_err("Scanning being aborted: status (%lu)\n",
 755                          cfg->scan_status);
 756                return -EAGAIN;
 757        }
 758        if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
 759                brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
 760                return -EAGAIN;
 761        }
 762
 763        /* Arm scan timeout timer */
 764        mod_timer(&cfg->escan_timeout, jiffies +
 765                        WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
 766
 767        escan_req = false;
 768        if (request) {
 769                /* scan bss */
 770                ssids = request->ssids;
 771                escan_req = true;
 772        } else {
 773                /* scan in ibss */
 774                /* we don't do escan in ibss */
 775                ssids = this_ssid;
 776        }
 777
 778        cfg->scan_request = request;
 779        set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
 780        if (escan_req) {
 781                err = brcmf_do_escan(cfg, wiphy, ndev, request);
 782                if (err)
 783                        goto scan_out;
 784        } else {
 785                brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
 786                          ssids->ssid, ssids->ssid_len);
 787                memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
 788                SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
 789                sr->ssid_le.SSID_len = cpu_to_le32(0);
 790                spec_scan = false;
 791                if (SSID_len) {
 792                        memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
 793                        sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
 794                        spec_scan = true;
 795                } else
 796                        brcmf_dbg(SCAN, "Broadcast scan\n");
 797
 798                passive_scan = cfg->active_scan ? 0 : 1;
 799                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
 800                                            passive_scan);
 801                if (err) {
 802                        brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
 803                        goto scan_out;
 804                }
 805                brcmf_set_mpc(ndev, 0);
 806                err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
 807                                             &sr->ssid_le, sizeof(sr->ssid_le));
 808                if (err) {
 809                        if (err == -EBUSY)
 810                                brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
 811                                          sr->ssid_le.SSID);
 812                        else
 813                                brcmf_err("WLC_SCAN error (%d)\n", err);
 814
 815                        brcmf_set_mpc(ndev, 1);
 816                        goto scan_out;
 817                }
 818        }
 819
 820        return 0;
 821
 822scan_out:
 823        clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
 824        if (timer_pending(&cfg->escan_timeout))
 825                del_timer_sync(&cfg->escan_timeout);
 826        cfg->scan_request = NULL;
 827        return err;
 828}
 829
 830static s32
 831brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 832{
 833        struct net_device *ndev = request->wdev->netdev;
 834        s32 err = 0;
 835
 836        brcmf_dbg(TRACE, "Enter\n");
 837
 838        if (!check_vif_up(container_of(request->wdev,
 839                                       struct brcmf_cfg80211_vif, wdev)))
 840                return -EIO;
 841
 842        err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
 843
 844        if (err)
 845                brcmf_err("scan error (%d)\n", err);
 846
 847        brcmf_dbg(TRACE, "Exit\n");
 848        return err;
 849}
 850
 851static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
 852{
 853        s32 err = 0;
 854
 855        err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
 856                                      rts_threshold);
 857        if (err)
 858                brcmf_err("Error (%d)\n", err);
 859
 860        return err;
 861}
 862
 863static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
 864{
 865        s32 err = 0;
 866
 867        err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
 868                                      frag_threshold);
 869        if (err)
 870                brcmf_err("Error (%d)\n", err);
 871
 872        return err;
 873}
 874
 875static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
 876{
 877        s32 err = 0;
 878        u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);
 879
 880        err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
 881        if (err) {
 882                brcmf_err("cmd (%d) , error (%d)\n", cmd, err);
 883                return err;
 884        }
 885        return err;
 886}
 887
 888static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 889{
 890        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 891        struct net_device *ndev = cfg_to_ndev(cfg);
 892        struct brcmf_if *ifp = netdev_priv(ndev);
 893        s32 err = 0;
 894
 895        brcmf_dbg(TRACE, "Enter\n");
 896        if (!check_vif_up(ifp->vif))
 897                return -EIO;
 898
 899        if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
 900            (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
 901                cfg->conf->rts_threshold = wiphy->rts_threshold;
 902                err = brcmf_set_rts(ndev, cfg->conf->rts_threshold);
 903                if (!err)
 904                        goto done;
 905        }
 906        if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
 907            (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
 908                cfg->conf->frag_threshold = wiphy->frag_threshold;
 909                err = brcmf_set_frag(ndev, cfg->conf->frag_threshold);
 910                if (!err)
 911                        goto done;
 912        }
 913        if (changed & WIPHY_PARAM_RETRY_LONG
 914            && (cfg->conf->retry_long != wiphy->retry_long)) {
 915                cfg->conf->retry_long = wiphy->retry_long;
 916                err = brcmf_set_retry(ndev, cfg->conf->retry_long, true);
 917                if (!err)
 918                        goto done;
 919        }
 920        if (changed & WIPHY_PARAM_RETRY_SHORT
 921            && (cfg->conf->retry_short != wiphy->retry_short)) {
 922                cfg->conf->retry_short = wiphy->retry_short;
 923                err = brcmf_set_retry(ndev, cfg->conf->retry_short, false);
 924                if (!err)
 925                        goto done;
 926        }
 927
 928done:
 929        brcmf_dbg(TRACE, "Exit\n");
 930        return err;
 931}
 932
 933static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
 934{
 935        memset(prof, 0, sizeof(*prof));
 936}
 937
 938static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
 939        size_t *join_params_size)
 940{
 941        u16 chanspec = 0;
 942
 943        if (ch != 0) {
 944                if (ch <= CH_MAX_2G_CHANNEL)
 945                        chanspec |= WL_CHANSPEC_BAND_2G;
 946                else
 947                        chanspec |= WL_CHANSPEC_BAND_5G;
 948
 949                chanspec |= WL_CHANSPEC_BW_20;
 950                chanspec |= WL_CHANSPEC_CTL_SB_NONE;
 951
 952                *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
 953                                     sizeof(u16);
 954
 955                chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
 956                join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
 957                join_params->params_le.chanspec_num = cpu_to_le32(1);
 958
 959                brcmf_dbg(CONN, "channel %d, chanspec %#X\n", ch, chanspec);
 960        }
 961}
 962
 963static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
 964{
 965        s32 err = 0;
 966
 967        brcmf_dbg(TRACE, "Enter\n");
 968
 969        if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
 970                brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n ");
 971                err = brcmf_fil_cmd_data_set(vif->ifp,
 972                                             BRCMF_C_DISASSOC, NULL, 0);
 973                if (err)
 974                        brcmf_err("WLC_DISASSOC failed (%d)\n", err);
 975                clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
 976        }
 977        clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
 978        brcmf_dbg(TRACE, "Exit\n");
 979}
 980
 981static s32
 982brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 983                      struct cfg80211_ibss_params *params)
 984{
 985        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 986        struct brcmf_if *ifp = netdev_priv(ndev);
 987        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 988        struct brcmf_join_params join_params;
 989        size_t join_params_size = 0;
 990        s32 err = 0;
 991        s32 wsec = 0;
 992        s32 bcnprd;
 993
 994        brcmf_dbg(TRACE, "Enter\n");
 995        if (!check_vif_up(ifp->vif))
 996                return -EIO;
 997
 998        if (params->ssid)
 999                brcmf_dbg(CONN, "SSID: %s\n", params->ssid);
1000        else {
1001                brcmf_dbg(CONN, "SSID: NULL, Not supported\n");
1002                return -EOPNOTSUPP;
1003        }
1004
1005        set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1006
1007        if (params->bssid)
1008                brcmf_dbg(CONN, "BSSID: %pM\n", params->bssid);
1009        else
1010                brcmf_dbg(CONN, "No BSSID specified\n");
1011
1012        if (params->chandef.chan)
1013                brcmf_dbg(CONN, "channel: %d\n",
1014                          params->chandef.chan->center_freq);
1015        else
1016                brcmf_dbg(CONN, "no channel specified\n");
1017
1018        if (params->channel_fixed)
1019                brcmf_dbg(CONN, "fixed channel required\n");
1020        else
1021                brcmf_dbg(CONN, "no fixed channel required\n");
1022
1023        if (params->ie && params->ie_len)
1024                brcmf_dbg(CONN, "ie len: %d\n", params->ie_len);
1025        else
1026                brcmf_dbg(CONN, "no ie specified\n");
1027
1028        if (params->beacon_interval)
1029                brcmf_dbg(CONN, "beacon interval: %d\n",
1030                          params->beacon_interval);
1031        else
1032                brcmf_dbg(CONN, "no beacon interval specified\n");
1033
1034        if (params->basic_rates)
1035                brcmf_dbg(CONN, "basic rates: %08X\n", params->basic_rates);
1036        else
1037                brcmf_dbg(CONN, "no basic rates specified\n");
1038
1039        if (params->privacy)
1040                brcmf_dbg(CONN, "privacy required\n");
1041        else
1042                brcmf_dbg(CONN, "no privacy required\n");
1043
1044        /* Configure Privacy for starter */
1045        if (params->privacy)
1046                wsec |= WEP_ENABLED;
1047
1048        err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
1049        if (err) {
1050                brcmf_err("wsec failed (%d)\n", err);
1051                goto done;
1052        }
1053
1054        /* Configure Beacon Interval for starter */
1055        if (params->beacon_interval)
1056                bcnprd = params->beacon_interval;
1057        else
1058                bcnprd = 100;
1059
1060        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);
1061        if (err) {
1062                brcmf_err("WLC_SET_BCNPRD failed (%d)\n", err);
1063                goto done;
1064        }
1065
1066        /* Configure required join parameter */
1067        memset(&join_params, 0, sizeof(struct brcmf_join_params));
1068
1069        /* SSID */
1070        profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32);
1071        memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len);
1072        memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len);
1073        join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1074        join_params_size = sizeof(join_params.ssid_le);
1075
1076        /* BSSID */
1077        if (params->bssid) {
1078                memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
1079                join_params_size = sizeof(join_params.ssid_le) +
1080                                   BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1081                memcpy(profile->bssid, params->bssid, ETH_ALEN);
1082        } else {
1083                memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
1084                memset(profile->bssid, 0, ETH_ALEN);
1085        }
1086
1087        /* Channel */
1088        if (params->chandef.chan) {
1089                u32 target_channel;
1090
1091                cfg->channel =
1092                        ieee80211_frequency_to_channel(
1093                                params->chandef.chan->center_freq);
1094                if (params->channel_fixed) {
1095                        /* adding chanspec */
1096                        brcmf_ch_to_chanspec(cfg->channel,
1097                                &join_params, &join_params_size);
1098                }
1099
1100                /* set channel for starter */
1101                target_channel = cfg->channel;
1102                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,
1103                                            target_channel);
1104                if (err) {
1105                        brcmf_err("WLC_SET_CHANNEL failed (%d)\n", err);
1106                        goto done;
1107                }
1108        } else
1109                cfg->channel = 0;
1110
1111        cfg->ibss_starter = false;
1112
1113
1114        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1115                                     &join_params, join_params_size);
1116        if (err) {
1117                brcmf_err("WLC_SET_SSID failed (%d)\n", err);
1118                goto done;
1119        }
1120
1121done:
1122        if (err)
1123                clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1124        brcmf_dbg(TRACE, "Exit\n");
1125        return err;
1126}
1127
1128static s32
1129brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1130{
1131        struct brcmf_if *ifp = netdev_priv(ndev);
1132        s32 err = 0;
1133
1134        brcmf_dbg(TRACE, "Enter\n");
1135        if (!check_vif_up(ifp->vif))
1136                return -EIO;
1137
1138        brcmf_link_down(ifp->vif);
1139
1140        brcmf_dbg(TRACE, "Exit\n");
1141
1142        return err;
1143}
1144
1145static s32 brcmf_set_wpa_version(struct net_device *ndev,
1146                                 struct cfg80211_connect_params *sme)
1147{
1148        struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1149        struct brcmf_cfg80211_security *sec;
1150        s32 val = 0;
1151        s32 err = 0;
1152
1153        if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1154                val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1155        else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1156                val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1157        else
1158                val = WPA_AUTH_DISABLED;
1159        brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
1160        err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val);
1161        if (err) {
1162                brcmf_err("set wpa_auth failed (%d)\n", err);
1163                return err;
1164        }
1165        sec = &profile->sec;
1166        sec->wpa_versions = sme->crypto.wpa_versions;
1167        return err;
1168}
1169
1170static s32 brcmf_set_auth_type(struct net_device *ndev,
1171                               struct cfg80211_connect_params *sme)
1172{
1173        struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1174        struct brcmf_cfg80211_security *sec;
1175        s32 val = 0;
1176        s32 err = 0;
1177
1178        switch (sme->auth_type) {
1179        case NL80211_AUTHTYPE_OPEN_SYSTEM:
1180                val = 0;
1181                brcmf_dbg(CONN, "open system\n");
1182                break;
1183        case NL80211_AUTHTYPE_SHARED_KEY:
1184                val = 1;
1185                brcmf_dbg(CONN, "shared key\n");
1186                break;
1187        case NL80211_AUTHTYPE_AUTOMATIC:
1188                val = 2;
1189                brcmf_dbg(CONN, "automatic\n");
1190                break;
1191        case NL80211_AUTHTYPE_NETWORK_EAP:
1192                brcmf_dbg(CONN, "network eap\n");
1193        default:
1194                val = 2;
1195                brcmf_err("invalid auth type (%d)\n", sme->auth_type);
1196                break;
1197        }
1198
1199        err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val);
1200        if (err) {
1201                brcmf_err("set auth failed (%d)\n", err);
1202                return err;
1203        }
1204        sec = &profile->sec;
1205        sec->auth_type = sme->auth_type;
1206        return err;
1207}
1208
1209static s32
1210brcmf_set_set_cipher(struct net_device *ndev,
1211                     struct cfg80211_connect_params *sme)
1212{
1213        struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1214        struct brcmf_cfg80211_security *sec;
1215        s32 pval = 0;
1216        s32 gval = 0;
1217        s32 err = 0;
1218
1219        if (sme->crypto.n_ciphers_pairwise) {
1220                switch (sme->crypto.ciphers_pairwise[0]) {
1221                case WLAN_CIPHER_SUITE_WEP40:
1222                case WLAN_CIPHER_SUITE_WEP104:
1223                        pval = WEP_ENABLED;
1224                        break;
1225                case WLAN_CIPHER_SUITE_TKIP:
1226                        pval = TKIP_ENABLED;
1227                        break;
1228                case WLAN_CIPHER_SUITE_CCMP:
1229                        pval = AES_ENABLED;
1230                        break;
1231                case WLAN_CIPHER_SUITE_AES_CMAC:
1232                        pval = AES_ENABLED;
1233                        break;
1234                default:
1235                        brcmf_err("invalid cipher pairwise (%d)\n",
1236                                  sme->crypto.ciphers_pairwise[0]);
1237                        return -EINVAL;
1238                }
1239        }
1240        if (sme->crypto.cipher_group) {
1241                switch (sme->crypto.cipher_group) {
1242                case WLAN_CIPHER_SUITE_WEP40:
1243                case WLAN_CIPHER_SUITE_WEP104:
1244                        gval = WEP_ENABLED;
1245                        break;
1246                case WLAN_CIPHER_SUITE_TKIP:
1247                        gval = TKIP_ENABLED;
1248                        break;
1249                case WLAN_CIPHER_SUITE_CCMP:
1250                        gval = AES_ENABLED;
1251                        break;
1252                case WLAN_CIPHER_SUITE_AES_CMAC:
1253                        gval = AES_ENABLED;
1254                        break;
1255                default:
1256                        brcmf_err("invalid cipher group (%d)\n",
1257                                  sme->crypto.cipher_group);
1258                        return -EINVAL;
1259                }
1260        }
1261
1262        brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);
1263        err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval);
1264        if (err) {
1265                brcmf_err("error (%d)\n", err);
1266                return err;
1267        }
1268
1269        sec = &profile->sec;
1270        sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1271        sec->cipher_group = sme->crypto.cipher_group;
1272
1273        return err;
1274}
1275
1276static s32
1277brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1278{
1279        struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1280        struct brcmf_cfg80211_security *sec;
1281        s32 val = 0;
1282        s32 err = 0;
1283
1284        if (sme->crypto.n_akm_suites) {
1285                err = brcmf_fil_iovar_int_get(netdev_priv(ndev),
1286                                              "wpa_auth", &val);
1287                if (err) {
1288                        brcmf_err("could not get wpa_auth (%d)\n", err);
1289                        return err;
1290                }
1291                if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1292                        switch (sme->crypto.akm_suites[0]) {
1293                        case WLAN_AKM_SUITE_8021X:
1294                                val = WPA_AUTH_UNSPECIFIED;
1295                                break;
1296                        case WLAN_AKM_SUITE_PSK:
1297                                val = WPA_AUTH_PSK;
1298                                break;
1299                        default:
1300                                brcmf_err("invalid cipher group (%d)\n",
1301                                          sme->crypto.cipher_group);
1302                                return -EINVAL;
1303                        }
1304                } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1305                        switch (sme->crypto.akm_suites[0]) {
1306                        case WLAN_AKM_SUITE_8021X:
1307                                val = WPA2_AUTH_UNSPECIFIED;
1308                                break;
1309                        case WLAN_AKM_SUITE_PSK:
1310                                val = WPA2_AUTH_PSK;
1311                                break;
1312                        default:
1313                                brcmf_err("invalid cipher group (%d)\n",
1314                                          sme->crypto.cipher_group);
1315                                return -EINVAL;
1316                        }
1317                }
1318
1319                brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
1320                err = brcmf_fil_iovar_int_set(netdev_priv(ndev),
1321                                              "wpa_auth", val);
1322                if (err) {
1323                        brcmf_err("could not set wpa_auth (%d)\n", err);
1324                        return err;
1325                }
1326        }
1327        sec = &profile->sec;
1328        sec->wpa_auth = sme->crypto.akm_suites[0];
1329
1330        return err;
1331}
1332
1333static s32
1334brcmf_set_sharedkey(struct net_device *ndev,
1335                    struct cfg80211_connect_params *sme)
1336{
1337        struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1338        struct brcmf_cfg80211_security *sec;
1339        struct brcmf_wsec_key key;
1340        s32 val;
1341        s32 err = 0;
1342
1343        brcmf_dbg(CONN, "key len (%d)\n", sme->key_len);
1344
1345        if (sme->key_len == 0)
1346                return 0;
1347
1348        sec = &profile->sec;
1349        brcmf_dbg(CONN, "wpa_versions 0x%x cipher_pairwise 0x%x\n",
1350                  sec->wpa_versions, sec->cipher_pairwise);
1351
1352        if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1353                return 0;
1354
1355        if (!(sec->cipher_pairwise &
1356            (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))
1357                return 0;
1358
1359        memset(&key, 0, sizeof(key));
1360        key.len = (u32) sme->key_len;
1361        key.index = (u32) sme->key_idx;
1362        if (key.len > sizeof(key.data)) {
1363                brcmf_err("Too long key length (%u)\n", key.len);
1364                return -EINVAL;
1365        }
1366        memcpy(key.data, sme->key, key.len);
1367        key.flags = BRCMF_PRIMARY_KEY;
1368        switch (sec->cipher_pairwise) {
1369        case WLAN_CIPHER_SUITE_WEP40:
1370                key.algo = CRYPTO_ALGO_WEP1;
1371                break;
1372        case WLAN_CIPHER_SUITE_WEP104:
1373                key.algo = CRYPTO_ALGO_WEP128;
1374                break;
1375        default:
1376                brcmf_err("Invalid algorithm (%d)\n",
1377                          sme->crypto.ciphers_pairwise[0]);
1378                return -EINVAL;
1379        }
1380        /* Set the new key/index */
1381        brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
1382                  key.len, key.index, key.algo);
1383        brcmf_dbg(CONN, "key \"%s\"\n", key.data);
1384        err = send_key_to_dongle(ndev, &key);
1385        if (err)
1386                return err;
1387
1388        if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
1389                brcmf_dbg(CONN, "set auth_type to shared key\n");
1390                val = WL_AUTH_SHARED_KEY;       /* shared key */
1391                err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
1392                if (err)
1393                        brcmf_err("set auth failed (%d)\n", err);
1394        }
1395        return err;
1396}
1397
1398static s32
1399brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1400                    struct cfg80211_connect_params *sme)
1401{
1402        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1403        struct brcmf_if *ifp = netdev_priv(ndev);
1404        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1405        struct ieee80211_channel *chan = sme->channel;
1406        struct brcmf_join_params join_params;
1407        size_t join_params_size;
1408        struct brcmf_ssid ssid;
1409
1410        s32 err = 0;
1411
1412        brcmf_dbg(TRACE, "Enter\n");
1413        if (!check_vif_up(ifp->vif))
1414                return -EIO;
1415
1416        if (!sme->ssid) {
1417                brcmf_err("Invalid ssid\n");
1418                return -EOPNOTSUPP;
1419        }
1420
1421        set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1422
1423        if (chan) {
1424                cfg->channel =
1425                        ieee80211_frequency_to_channel(chan->center_freq);
1426                brcmf_dbg(CONN, "channel (%d), center_req (%d)\n",
1427                          cfg->channel, chan->center_freq);
1428        } else
1429                cfg->channel = 0;
1430
1431        brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1432
1433        err = brcmf_set_wpa_version(ndev, sme);
1434        if (err) {
1435                brcmf_err("wl_set_wpa_version failed (%d)\n", err);
1436                goto done;
1437        }
1438
1439        err = brcmf_set_auth_type(ndev, sme);
1440        if (err) {
1441                brcmf_err("wl_set_auth_type failed (%d)\n", err);
1442                goto done;
1443        }
1444
1445        err = brcmf_set_set_cipher(ndev, sme);
1446        if (err) {
1447                brcmf_err("wl_set_set_cipher failed (%d)\n", err);
1448                goto done;
1449        }
1450
1451        err = brcmf_set_key_mgmt(ndev, sme);
1452        if (err) {
1453                brcmf_err("wl_set_key_mgmt failed (%d)\n", err);
1454                goto done;
1455        }
1456
1457        err = brcmf_set_sharedkey(ndev, sme);
1458        if (err) {
1459                brcmf_err("brcmf_set_sharedkey failed (%d)\n", err);
1460                goto done;
1461        }
1462
1463        memset(&join_params, 0, sizeof(join_params));
1464        join_params_size = sizeof(join_params.ssid_le);
1465
1466        profile->ssid.SSID_len = min_t(u32,
1467                                       sizeof(ssid.SSID), (u32)sme->ssid_len);
1468        memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len);
1469        memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
1470        join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1471
1472        memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
1473
1474        if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
1475                brcmf_dbg(CONN, "ssid \"%s\", len (%d)\n",
1476                          ssid.SSID, ssid.SSID_len);
1477
1478        brcmf_ch_to_chanspec(cfg->channel,
1479                             &join_params, &join_params_size);
1480        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1481                                     &join_params, join_params_size);
1482        if (err)
1483                brcmf_err("WLC_SET_SSID failed (%d)\n", err);
1484
1485done:
1486        if (err)
1487                clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1488        brcmf_dbg(TRACE, "Exit\n");
1489        return err;
1490}
1491
1492static s32
1493brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1494                       u16 reason_code)
1495{
1496        struct brcmf_if *ifp = netdev_priv(ndev);
1497        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1498        struct brcmf_scb_val_le scbval;
1499        s32 err = 0;
1500
1501        brcmf_dbg(TRACE, "Enter. Reason code = %d\n", reason_code);
1502        if (!check_vif_up(ifp->vif))
1503                return -EIO;
1504
1505        clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
1506
1507        memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
1508        scbval.val = cpu_to_le32(reason_code);
1509        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
1510                                     &scbval, sizeof(scbval));
1511        if (err)
1512                brcmf_err("error (%d)\n", err);
1513
1514        brcmf_dbg(TRACE, "Exit\n");
1515        return err;
1516}
1517
1518static s32
1519brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
1520                            enum nl80211_tx_power_setting type, s32 mbm)
1521{
1522
1523        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1524        struct net_device *ndev = cfg_to_ndev(cfg);
1525        struct brcmf_if *ifp = netdev_priv(ndev);
1526        u16 txpwrmw;
1527        s32 err = 0;
1528        s32 disable = 0;
1529        s32 dbm = MBM_TO_DBM(mbm);
1530
1531        brcmf_dbg(TRACE, "Enter\n");
1532        if (!check_vif_up(ifp->vif))
1533                return -EIO;
1534
1535        switch (type) {
1536        case NL80211_TX_POWER_AUTOMATIC:
1537                break;
1538        case NL80211_TX_POWER_LIMITED:
1539        case NL80211_TX_POWER_FIXED:
1540                if (dbm < 0) {
1541                        brcmf_err("TX_POWER_FIXED - dbm is negative\n");
1542                        err = -EINVAL;
1543                        goto done;
1544                }
1545                break;
1546        }
1547        /* Make sure radio is off or on as far as software is concerned */
1548        disable = WL_RADIO_SW_DISABLE << 16;
1549        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
1550        if (err)
1551                brcmf_err("WLC_SET_RADIO error (%d)\n", err);
1552
1553        if (dbm > 0xffff)
1554                txpwrmw = 0xffff;
1555        else
1556                txpwrmw = (u16) dbm;
1557        err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
1558                                      (s32)brcmf_mw_to_qdbm(txpwrmw));
1559        if (err)
1560                brcmf_err("qtxpower error (%d)\n", err);
1561        cfg->conf->tx_power = dbm;
1562
1563done:
1564        brcmf_dbg(TRACE, "Exit\n");
1565        return err;
1566}
1567
1568static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy,
1569                                       struct wireless_dev *wdev,
1570                                       s32 *dbm)
1571{
1572        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1573        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
1574        s32 txpwrdbm;
1575        u8 result;
1576        s32 err = 0;
1577
1578        brcmf_dbg(TRACE, "Enter\n");
1579        if (!check_vif_up(ifp->vif))
1580                return -EIO;
1581
1582        err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
1583        if (err) {
1584                brcmf_err("error (%d)\n", err);
1585                goto done;
1586        }
1587
1588        result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1589        *dbm = (s32) brcmf_qdbm_to_mw(result);
1590
1591done:
1592        brcmf_dbg(TRACE, "Exit\n");
1593        return err;
1594}
1595
1596static s32
1597brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
1598                               u8 key_idx, bool unicast, bool multicast)
1599{
1600        struct brcmf_if *ifp = netdev_priv(ndev);
1601        u32 index;
1602        u32 wsec;
1603        s32 err = 0;
1604
1605        brcmf_dbg(TRACE, "Enter\n");
1606        brcmf_dbg(CONN, "key index (%d)\n", key_idx);
1607        if (!check_vif_up(ifp->vif))
1608                return -EIO;
1609
1610        err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
1611        if (err) {
1612                brcmf_err("WLC_GET_WSEC error (%d)\n", err);
1613                goto done;
1614        }
1615
1616        if (wsec & WEP_ENABLED) {
1617                /* Just select a new current key */
1618                index = key_idx;
1619                err = brcmf_fil_cmd_int_set(ifp,
1620                                            BRCMF_C_SET_KEY_PRIMARY, index);
1621                if (err)
1622                        brcmf_err("error (%d)\n", err);
1623        }
1624done:
1625        brcmf_dbg(TRACE, "Exit\n");
1626        return err;
1627}
1628
1629static s32
1630brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
1631              u8 key_idx, const u8 *mac_addr, struct key_params *params)
1632{
1633        struct brcmf_wsec_key key;
1634        s32 err = 0;
1635
1636        memset(&key, 0, sizeof(key));
1637        key.index = (u32) key_idx;
1638        /* Instead of bcast for ea address for default wep keys,
1639                 driver needs it to be Null */
1640        if (!is_multicast_ether_addr(mac_addr))
1641                memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1642        key.len = (u32) params->key_len;
1643        /* check for key index change */
1644        if (key.len == 0) {
1645                /* key delete */
1646                err = send_key_to_dongle(ndev, &key);
1647                if (err)
1648                        brcmf_err("key delete error (%d)\n", err);
1649        } else {
1650                if (key.len > sizeof(key.data)) {
1651                        brcmf_err("Invalid key length (%d)\n", key.len);
1652                        return -EINVAL;
1653                }
1654
1655                brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
1656                memcpy(key.data, params->key, key.len);
1657
1658                if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1659                        u8 keybuf[8];
1660                        memcpy(keybuf, &key.data[24], sizeof(keybuf));
1661                        memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1662                        memcpy(&key.data[16], keybuf, sizeof(keybuf));
1663                }
1664
1665                /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1666                if (params->seq && params->seq_len == 6) {
1667                        /* rx iv */
1668                        u8 *ivptr;
1669                        ivptr = (u8 *) params->seq;
1670                        key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1671                            (ivptr[3] << 8) | ivptr[2];
1672                        key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1673                        key.iv_initialized = true;
1674                }
1675
1676                switch (params->cipher) {
1677                case WLAN_CIPHER_SUITE_WEP40:
1678                        key.algo = CRYPTO_ALGO_WEP1;
1679                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
1680                        break;
1681                case WLAN_CIPHER_SUITE_WEP104:
1682                        key.algo = CRYPTO_ALGO_WEP128;
1683                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
1684                        break;
1685                case WLAN_CIPHER_SUITE_TKIP:
1686                        key.algo = CRYPTO_ALGO_TKIP;
1687                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
1688                        break;
1689                case WLAN_CIPHER_SUITE_AES_CMAC:
1690                        key.algo = CRYPTO_ALGO_AES_CCM;
1691                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
1692                        break;
1693                case WLAN_CIPHER_SUITE_CCMP:
1694                        key.algo = CRYPTO_ALGO_AES_CCM;
1695                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
1696                        break;
1697                default:
1698                        brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
1699                        return -EINVAL;
1700                }
1701                err = send_key_to_dongle(ndev, &key);
1702                if (err)
1703                        brcmf_err("wsec_key error (%d)\n", err);
1704        }
1705        return err;
1706}
1707
1708static s32
1709brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1710                    u8 key_idx, bool pairwise, const u8 *mac_addr,
1711                    struct key_params *params)
1712{
1713        struct brcmf_if *ifp = netdev_priv(ndev);
1714        struct brcmf_wsec_key key;
1715        s32 val;
1716        s32 wsec;
1717        s32 err = 0;
1718        u8 keybuf[8];
1719
1720        brcmf_dbg(TRACE, "Enter\n");
1721        brcmf_dbg(CONN, "key index (%d)\n", key_idx);
1722        if (!check_vif_up(ifp->vif))
1723                return -EIO;
1724
1725        if (mac_addr) {
1726                brcmf_dbg(TRACE, "Exit");
1727                return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
1728        }
1729        memset(&key, 0, sizeof(key));
1730
1731        key.len = (u32) params->key_len;
1732        key.index = (u32) key_idx;
1733
1734        if (key.len > sizeof(key.data)) {
1735                brcmf_err("Too long key length (%u)\n", key.len);
1736                err = -EINVAL;
1737                goto done;
1738        }
1739        memcpy(key.data, params->key, key.len);
1740
1741        key.flags = BRCMF_PRIMARY_KEY;
1742        switch (params->cipher) {
1743        case WLAN_CIPHER_SUITE_WEP40:
1744                key.algo = CRYPTO_ALGO_WEP1;
1745                val = WEP_ENABLED;
1746                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
1747                break;
1748        case WLAN_CIPHER_SUITE_WEP104:
1749                key.algo = CRYPTO_ALGO_WEP128;
1750                val = WEP_ENABLED;
1751                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
1752                break;
1753        case WLAN_CIPHER_SUITE_TKIP:
1754                if (ifp->vif->mode != WL_MODE_AP) {
1755                        brcmf_dbg(CONN, "Swapping key\n");
1756                        memcpy(keybuf, &key.data[24], sizeof(keybuf));
1757                        memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1758                        memcpy(&key.data[16], keybuf, sizeof(keybuf));
1759                }
1760                key.algo = CRYPTO_ALGO_TKIP;
1761                val = TKIP_ENABLED;
1762                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
1763                break;
1764        case WLAN_CIPHER_SUITE_AES_CMAC:
1765                key.algo = CRYPTO_ALGO_AES_CCM;
1766                val = AES_ENABLED;
1767                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
1768                break;
1769        case WLAN_CIPHER_SUITE_CCMP:
1770                key.algo = CRYPTO_ALGO_AES_CCM;
1771                val = AES_ENABLED;
1772                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
1773                break;
1774        default:
1775                brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
1776                err = -EINVAL;
1777                goto done;
1778        }
1779
1780        err = send_key_to_dongle(ndev, &key);
1781        if (err)
1782                goto done;
1783
1784        err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
1785        if (err) {
1786                brcmf_err("get wsec error (%d)\n", err);
1787                goto done;
1788        }
1789        wsec |= val;
1790        err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
1791        if (err) {
1792                brcmf_err("set wsec error (%d)\n", err);
1793                goto done;
1794        }
1795
1796done:
1797        brcmf_dbg(TRACE, "Exit\n");
1798        return err;
1799}
1800
1801static s32
1802brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1803                    u8 key_idx, bool pairwise, const u8 *mac_addr)
1804{
1805        struct brcmf_if *ifp = netdev_priv(ndev);
1806        struct brcmf_wsec_key key;
1807        s32 err = 0;
1808
1809        brcmf_dbg(TRACE, "Enter\n");
1810        if (!check_vif_up(ifp->vif))
1811                return -EIO;
1812
1813        if (key_idx >= DOT11_MAX_DEFAULT_KEYS) {
1814                /* we ignore this key index in this case */
1815                brcmf_err("invalid key index (%d)\n", key_idx);
1816                return -EINVAL;
1817        }
1818
1819        memset(&key, 0, sizeof(key));
1820
1821        key.index = (u32) key_idx;
1822        key.flags = BRCMF_PRIMARY_KEY;
1823        key.algo = CRYPTO_ALGO_OFF;
1824
1825        brcmf_dbg(CONN, "key index (%d)\n", key_idx);
1826
1827        /* Set the new key/index */
1828        err = send_key_to_dongle(ndev, &key);
1829
1830        brcmf_dbg(TRACE, "Exit\n");
1831        return err;
1832}
1833
1834static s32
1835brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1836                    u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
1837                    void (*callback) (void *cookie, struct key_params * params))
1838{
1839        struct key_params params;
1840        struct brcmf_if *ifp = netdev_priv(ndev);
1841        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1842        struct brcmf_cfg80211_security *sec;
1843        s32 wsec;
1844        s32 err = 0;
1845
1846        brcmf_dbg(TRACE, "Enter\n");
1847        brcmf_dbg(CONN, "key index (%d)\n", key_idx);
1848        if (!check_vif_up(ifp->vif))
1849                return -EIO;
1850
1851        memset(&params, 0, sizeof(params));
1852
1853        err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
1854        if (err) {
1855                brcmf_err("WLC_GET_WSEC error (%d)\n", err);
1856                /* Ignore this error, may happen during DISASSOC */
1857                err = -EAGAIN;
1858                goto done;
1859        }
1860        switch (wsec & ~SES_OW_ENABLED) {
1861        case WEP_ENABLED:
1862                sec = &profile->sec;
1863                if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
1864                        params.cipher = WLAN_CIPHER_SUITE_WEP40;
1865                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
1866                } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
1867                        params.cipher = WLAN_CIPHER_SUITE_WEP104;
1868                        brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
1869                }
1870                break;
1871        case TKIP_ENABLED:
1872                params.cipher = WLAN_CIPHER_SUITE_TKIP;
1873                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
1874                break;
1875        case AES_ENABLED:
1876                params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
1877                brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
1878                break;
1879        default:
1880                brcmf_err("Invalid algo (0x%x)\n", wsec);
1881                err = -EINVAL;
1882                goto done;
1883        }
1884        callback(cookie, &params);
1885
1886done:
1887        brcmf_dbg(TRACE, "Exit\n");
1888        return err;
1889}
1890
1891static s32
1892brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
1893                                    struct net_device *ndev, u8 key_idx)
1894{
1895        brcmf_dbg(INFO, "Not supported\n");
1896
1897        return -EOPNOTSUPP;
1898}
1899
1900static s32
1901brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
1902                           u8 *mac, struct station_info *sinfo)
1903{
1904        struct brcmf_if *ifp = netdev_priv(ndev);
1905        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1906        struct brcmf_scb_val_le scb_val;
1907        int rssi;
1908        s32 rate;
1909        s32 err = 0;
1910        u8 *bssid = profile->bssid;
1911        struct brcmf_sta_info_le sta_info_le;
1912
1913        brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
1914        if (!check_vif_up(ifp->vif))
1915                return -EIO;
1916
1917        if (ifp->vif->mode == WL_MODE_AP) {
1918                memcpy(&sta_info_le, mac, ETH_ALEN);
1919                err = brcmf_fil_iovar_data_get(ifp, "sta_info",
1920                                               &sta_info_le,
1921                                               sizeof(sta_info_le));
1922                if (err < 0) {
1923                        brcmf_err("GET STA INFO failed, %d\n", err);
1924                        goto done;
1925                }
1926                sinfo->filled = STATION_INFO_INACTIVE_TIME;
1927                sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
1928                if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
1929                        sinfo->filled |= STATION_INFO_CONNECTED_TIME;
1930                        sinfo->connected_time = le32_to_cpu(sta_info_le.in);
1931                }
1932                brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
1933                          sinfo->inactive_time, sinfo->connected_time);
1934        } else if (ifp->vif->mode == WL_MODE_BSS) {
1935                if (memcmp(mac, bssid, ETH_ALEN)) {
1936                        brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
1937                                  mac, bssid);
1938                        err = -ENOENT;
1939                        goto done;
1940                }
1941                /* Report the current tx rate */
1942        err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
1943                if (err) {
1944                        brcmf_err("Could not get rate (%d)\n", err);
1945                        goto done;
1946                } else {
1947                        sinfo->filled |= STATION_INFO_TX_BITRATE;
1948                        sinfo->txrate.legacy = rate * 5;
1949                        brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
1950                }
1951
1952                if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
1953                             &ifp->vif->sme_state)) {
1954                        memset(&scb_val, 0, sizeof(scb_val));
1955                        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
1956                                                     &scb_val, sizeof(scb_val));
1957                        if (err) {
1958                                brcmf_err("Could not get rssi (%d)\n", err);
1959                                goto done;
1960                        } else {
1961                                rssi = le32_to_cpu(scb_val.val);
1962                                sinfo->filled |= STATION_INFO_SIGNAL;
1963                                sinfo->signal = rssi;
1964                                brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
1965                        }
1966                }
1967        } else
1968                err = -EPERM;
1969done:
1970        brcmf_dbg(TRACE, "Exit\n");
1971        return err;
1972}
1973
1974static s32
1975brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
1976                           bool enabled, s32 timeout)
1977{
1978        s32 pm;
1979        s32 err = 0;
1980        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1981        struct brcmf_if *ifp = netdev_priv(ndev);
1982
1983        brcmf_dbg(TRACE, "Enter\n");
1984
1985        /*
1986         * Powersave enable/disable request is coming from the
1987         * cfg80211 even before the interface is up. In that
1988         * scenario, driver will be storing the power save
1989         * preference in cfg struct to apply this to
1990         * FW later while initializing the dongle
1991         */
1992        cfg->pwr_save = enabled;
1993        if (!check_vif_up(ifp->vif)) {
1994
1995                brcmf_dbg(INFO, "Device is not ready, storing the value in cfg_info struct\n");
1996                goto done;
1997        }
1998
1999        pm = enabled ? PM_FAST : PM_OFF;
2000        brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
2001
2002        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
2003        if (err) {
2004                if (err == -ENODEV)
2005                        brcmf_err("net_device is not ready yet\n");
2006                else
2007                        brcmf_err("error (%d)\n", err);
2008        }
2009done:
2010        brcmf_dbg(TRACE, "Exit\n");
2011        return err;
2012}
2013
2014static s32
2015brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
2016                             const u8 *addr,
2017                             const struct cfg80211_bitrate_mask *mask)
2018{
2019        struct brcmf_if *ifp = netdev_priv(ndev);
2020        struct brcm_rateset_le rateset_le;
2021        s32 rate;
2022        s32 val;
2023        s32 err_bg;
2024        s32 err_a;
2025        u32 legacy;
2026        s32 err = 0;
2027
2028        brcmf_dbg(TRACE, "Enter\n");
2029        if (!check_vif_up(ifp->vif))
2030                return -EIO;
2031
2032        /* addr param is always NULL. ignore it */
2033        /* Get current rateset */
2034        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CURR_RATESET,
2035                                     &rateset_le, sizeof(rateset_le));
2036        if (err) {
2037                brcmf_err("could not get current rateset (%d)\n", err);
2038                goto done;
2039        }
2040
2041        legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
2042        if (!legacy)
2043                legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
2044                             0xFFFF);
2045
2046        val = wl_g_rates[legacy - 1].bitrate * 100000;
2047
2048        if (val < le32_to_cpu(rateset_le.count))
2049                /* Select rate by rateset index */
2050                rate = rateset_le.rates[val] & 0x7f;
2051        else
2052                /* Specified rate in bps */
2053                rate = val / 500000;
2054
2055        brcmf_dbg(CONN, "rate %d mbps\n", rate / 2);
2056
2057        /*
2058         *
2059         *      Set rate override,
2060         *      Since the is a/b/g-blind, both a/bg_rate are enforced.
2061         */
2062        err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate);
2063        err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate);
2064        if (err_bg && err_a) {
2065                brcmf_err("could not set fixed rate (%d) (%d)\n", err_bg,
2066                          err_a);
2067                err = err_bg | err_a;
2068        }
2069
2070done:
2071        brcmf_dbg(TRACE, "Exit\n");
2072        return err;
2073}
2074
2075static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
2076                                   struct brcmf_bss_info_le *bi)
2077{
2078        struct wiphy *wiphy = cfg_to_wiphy(cfg);
2079        struct ieee80211_channel *notify_channel;
2080        struct cfg80211_bss *bss;
2081        struct ieee80211_supported_band *band;
2082        s32 err = 0;
2083        u16 channel;
2084        u32 freq;
2085        u16 notify_capability;
2086        u16 notify_interval;
2087        u8 *notify_ie;
2088        size_t notify_ielen;
2089        s32 notify_signal;
2090
2091        if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2092                brcmf_err("Bss info is larger than buffer. Discarding\n");
2093                return 0;
2094        }
2095
2096        channel = bi->ctl_ch ? bi->ctl_ch :
2097                                CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2098
2099        if (channel <= CH_MAX_2G_CHANNEL)
2100                band = wiphy->bands[IEEE80211_BAND_2GHZ];
2101        else
2102                band = wiphy->bands[IEEE80211_BAND_5GHZ];
2103
2104        freq = ieee80211_channel_to_frequency(channel, band->band);
2105        notify_channel = ieee80211_get_channel(wiphy, freq);
2106
2107        notify_capability = le16_to_cpu(bi->capability);
2108        notify_interval = le16_to_cpu(bi->beacon_period);
2109        notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2110        notify_ielen = le32_to_cpu(bi->ie_length);
2111        notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2112
2113        brcmf_dbg(CONN, "bssid: %pM\n", bi->BSSID);
2114        brcmf_dbg(CONN, "Channel: %d(%d)\n", channel, freq);
2115        brcmf_dbg(CONN, "Capability: %X\n", notify_capability);
2116        brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
2117        brcmf_dbg(CONN, "Signal: %d\n", notify_signal);
2118
2119        bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2120                0, notify_capability, notify_interval, notify_ie,
2121                notify_ielen, notify_signal, GFP_KERNEL);
2122
2123        if (!bss)
2124                return -ENOMEM;
2125
2126        cfg80211_put_bss(bss);
2127
2128        return err;
2129}
2130
2131static struct brcmf_bss_info_le *
2132next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2133{
2134        if (bss == NULL)
2135                return list->bss_info_le;
2136        return (struct brcmf_bss_info_le *)((unsigned long)bss +
2137                                            le32_to_cpu(bss->length));
2138}
2139
2140static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
2141{
2142        struct brcmf_scan_results *bss_list;
2143        struct brcmf_bss_info_le *bi = NULL;    /* must be initialized */
2144        s32 err = 0;
2145        int i;
2146
2147        bss_list = cfg->bss_list;
2148        if (bss_list->count != 0 &&
2149            bss_list->version != BRCMF_BSS_INFO_VERSION) {
2150                brcmf_err("Version %d != WL_BSS_INFO_VERSION\n",
2151                          bss_list->version);
2152                return -EOPNOTSUPP;
2153        }
2154        brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count);
2155        for (i = 0; i < bss_list->count; i++) {
2156                bi = next_bss_le(bss_list, bi);
2157                err = brcmf_inform_single_bss(cfg, bi);
2158                if (err)
2159                        break;
2160        }
2161        return err;
2162}
2163
2164static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
2165                          struct net_device *ndev, const u8 *bssid)
2166{
2167        struct wiphy *wiphy = cfg_to_wiphy(cfg);
2168        struct ieee80211_channel *notify_channel;
2169        struct brcmf_bss_info_le *bi = NULL;
2170        struct ieee80211_supported_band *band;
2171        struct cfg80211_bss *bss;
2172        u8 *buf = NULL;
2173        s32 err = 0;
2174        u16 channel;
2175        u32 freq;
2176        u16 notify_capability;
2177        u16 notify_interval;
2178        u8 *notify_ie;
2179        size_t notify_ielen;
2180        s32 notify_signal;
2181
2182        brcmf_dbg(TRACE, "Enter\n");
2183
2184        buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2185        if (buf == NULL) {
2186                err = -ENOMEM;
2187                goto CleanUp;
2188        }
2189
2190        *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2191
2192        err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
2193                                     buf, WL_BSS_INFO_MAX);
2194        if (err) {
2195                brcmf_err("WLC_GET_BSS_INFO failed: %d\n", err);
2196                goto CleanUp;
2197        }
2198
2199        bi = (struct brcmf_bss_info_le *)(buf + 4);
2200
2201        channel = bi->ctl_ch ? bi->ctl_ch :
2202                                CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2203
2204        if (channel <= CH_MAX_2G_CHANNEL)
2205                band = wiphy->bands[IEEE80211_BAND_2GHZ];
2206        else
2207                band = wiphy->bands[IEEE80211_BAND_5GHZ];
2208
2209        freq = ieee80211_channel_to_frequency(channel, band->band);
2210        notify_channel = ieee80211_get_channel(wiphy, freq);
2211
2212        notify_capability = le16_to_cpu(bi->capability);
2213        notify_interval = le16_to_cpu(bi->beacon_period);
2214        notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2215        notify_ielen = le32_to_cpu(bi->ie_length);
2216        notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2217
2218        brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq);
2219        brcmf_dbg(CONN, "capability: %X\n", notify_capability);
2220        brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
2221        brcmf_dbg(CONN, "signal: %d\n", notify_signal);
2222
2223        bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
2224                0, notify_capability, notify_interval,
2225                notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2226
2227        if (!bss) {
2228                err = -ENOMEM;
2229                goto CleanUp;
2230        }
2231
2232        cfg80211_put_bss(bss);
2233
2234CleanUp:
2235
2236        kfree(buf);
2237
2238        brcmf_dbg(TRACE, "Exit\n");
2239
2240        return err;
2241}
2242
2243static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)
2244{
2245        return vif->mode == WL_MODE_IBSS;
2246}
2247
2248/*
2249 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2250 * triples, returning a pointer to the substring whose first element
2251 * matches tag
2252 */
2253static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2254{
2255        struct brcmf_tlv *elt;
2256        int totlen;
2257
2258        elt = (struct brcmf_tlv *) buf;
2259        totlen = buflen;
2260
2261        /* find tagged parameter */
2262        while (totlen >= TLV_HDR_LEN) {
2263                int len = elt->len;
2264
2265                /* validate remaining totlen */
2266                if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
2267                        return elt;
2268
2269                elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN));
2270                totlen -= (len + TLV_HDR_LEN);
2271        }
2272
2273        return NULL;
2274}
2275
2276/* Is any of the tlvs the expected entry? If
2277 * not update the tlvs buffer pointer/length.
2278 */
2279static bool
2280brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
2281                 u8 *oui, u32 oui_len, u8 type)
2282{
2283        /* If the contents match the OUI and the type */
2284        if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
2285            !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
2286            type == ie[TLV_BODY_OFF + oui_len]) {
2287                return true;
2288        }
2289
2290        if (tlvs == NULL)
2291                return false;
2292        /* point to the next ie */
2293        ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
2294        /* calculate the length of the rest of the buffer */
2295        *tlvs_len -= (int)(ie - *tlvs);
2296        /* update the pointer to the start of the buffer */
2297        *tlvs = ie;
2298
2299        return false;
2300}
2301
2302static struct brcmf_vs_tlv *
2303brcmf_find_wpaie(u8 *parse, u32 len)
2304{
2305        struct brcmf_tlv *ie;
2306
2307        while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
2308                if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
2309                                     WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
2310                        return (struct brcmf_vs_tlv *)ie;
2311        }
2312        return NULL;
2313}
2314
2315static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
2316{
2317        struct net_device *ndev = cfg_to_ndev(cfg);
2318        struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
2319        struct brcmf_if *ifp = netdev_priv(ndev);
2320        struct brcmf_bss_info_le *bi;
2321        struct brcmf_ssid *ssid;
2322        struct brcmf_tlv *tim;
2323        u16 beacon_interval;
2324        u8 dtim_period;
2325        size_t ie_len;
2326        u8 *ie;
2327        s32 err = 0;
2328
2329        brcmf_dbg(TRACE, "Enter\n");
2330        if (brcmf_is_ibssmode(ifp->vif))
2331                return err;
2332
2333        ssid = &profile->ssid;
2334
2335        *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2336        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
2337                                     cfg->extra_buf, WL_EXTRA_BUF_MAX);
2338        if (err) {
2339                brcmf_err("Could not get bss info %d\n", err);
2340                goto update_bss_info_out;
2341        }
2342
2343        bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4);
2344        err = brcmf_inform_single_bss(cfg, bi);
2345        if (err)
2346                goto update_bss_info_out;
2347
2348        ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2349        ie_len = le32_to_cpu(bi->ie_length);
2350        beacon_interval = le16_to_cpu(bi->beacon_period);
2351
2352        tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
2353        if (tim)
2354                dtim_period = tim->data[1];
2355        else {
2356                /*
2357                * active scan was done so we could not get dtim
2358                * information out of probe response.
2359                * so we speficially query dtim information to dongle.
2360                */
2361                u32 var;
2362                err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
2363                if (err) {
2364                        brcmf_err("wl dtim_assoc failed (%d)\n", err);
2365                        goto update_bss_info_out;
2366                }
2367                dtim_period = (u8)var;
2368        }
2369
2370update_bss_info_out:
2371        brcmf_dbg(TRACE, "Exit");
2372        return err;
2373}
2374
2375static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
2376{
2377        struct escan_info *escan = &cfg->escan_info;
2378
2379        set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
2380        if (cfg->scan_request) {
2381                escan->escan_state = WL_ESCAN_STATE_IDLE;
2382                brcmf_notify_escan_complete(cfg, escan->ndev, true, true);
2383        }
2384        clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2385        clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
2386}
2387
2388static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
2389{
2390        struct brcmf_cfg80211_info *cfg =
2391                        container_of(work, struct brcmf_cfg80211_info,
2392                                     escan_timeout_work);
2393
2394        brcmf_notify_escan_complete(cfg,
2395                cfg->escan_info.ndev, true, true);
2396}
2397
2398static void brcmf_escan_timeout(unsigned long data)
2399{
2400        struct brcmf_cfg80211_info *cfg =
2401                        (struct brcmf_cfg80211_info *)data;
2402
2403        if (cfg->scan_request) {
2404                brcmf_err("timer expired\n");
2405                schedule_work(&cfg->escan_timeout_work);
2406        }
2407}
2408
2409static s32
2410brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
2411                              struct brcmf_bss_info_le *bss_info_le)
2412{
2413        if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
2414                (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
2415                CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
2416                bss_info_le->SSID_len == bss->SSID_len &&
2417                !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
2418                if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
2419                        (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
2420                        s16 bss_rssi = le16_to_cpu(bss->RSSI);
2421                        s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
2422
2423                        /* preserve max RSSI if the measurements are
2424                        * both on-channel or both off-channel
2425                        */
2426                        if (bss_info_rssi > bss_rssi)
2427                                bss->RSSI = bss_info_le->RSSI;
2428                } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
2429                        (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
2430                        /* preserve the on-channel rssi measurement
2431                        * if the new measurement is off channel
2432                        */
2433                        bss->RSSI = bss_info_le->RSSI;
2434                        bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
2435                }
2436                return 1;
2437        }
2438        return 0;
2439}
2440
2441static s32
2442brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
2443                             const struct brcmf_event_msg *e, void *data)
2444{
2445        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
2446        struct net_device *ndev = ifp->ndev;
2447        s32 status;
2448        s32 err = 0;
2449        struct brcmf_escan_result_le *escan_result_le;
2450        struct brcmf_bss_info_le *bss_info_le;
2451        struct brcmf_bss_info_le *bss = NULL;
2452        u32 bi_length;
2453        struct brcmf_scan_results *list;
2454        u32 i;
2455        bool aborted;
2456
2457        status = e->status;
2458
2459        if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2460                brcmf_err("scan not ready ndev %p drv_status %x\n", ndev,
2461                          !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
2462                return -EPERM;
2463        }
2464
2465        if (status == BRCMF_E_STATUS_PARTIAL) {
2466                brcmf_dbg(SCAN, "ESCAN Partial result\n");
2467                escan_result_le = (struct brcmf_escan_result_le *) data;
2468                if (!escan_result_le) {
2469                        brcmf_err("Invalid escan result (NULL pointer)\n");
2470                        goto exit;
2471                }
2472                if (!cfg->scan_request) {
2473                        brcmf_dbg(SCAN, "result without cfg80211 request\n");
2474                        goto exit;
2475                }
2476
2477                if (le16_to_cpu(escan_result_le->bss_count) != 1) {
2478                        brcmf_err("Invalid bss_count %d: ignoring\n",
2479                                  escan_result_le->bss_count);
2480                        goto exit;
2481                }
2482                bss_info_le = &escan_result_le->bss_info_le;
2483
2484                bi_length = le32_to_cpu(bss_info_le->length);
2485                if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
2486                                        WL_ESCAN_RESULTS_FIXED_SIZE)) {
2487                        brcmf_err("Invalid bss_info length %d: ignoring\n",
2488                                  bi_length);
2489                        goto exit;
2490                }
2491
2492                if (!(cfg_to_wiphy(cfg)->interface_modes &
2493                                        BIT(NL80211_IFTYPE_ADHOC))) {
2494                        if (le16_to_cpu(bss_info_le->capability) &
2495                                                WLAN_CAPABILITY_IBSS) {
2496                                brcmf_err("Ignoring IBSS result\n");
2497                                goto exit;
2498                        }
2499                }
2500
2501                list = (struct brcmf_scan_results *)
2502                                cfg->escan_info.escan_buf;
2503                if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
2504                        brcmf_err("Buffer is too small: ignoring\n");
2505                        goto exit;
2506                }
2507
2508                for (i = 0; i < list->count; i++) {
2509                        bss = bss ? (struct brcmf_bss_info_le *)
2510                                ((unsigned char *)bss +
2511                                le32_to_cpu(bss->length)) : list->bss_info_le;
2512                        if (brcmf_compare_update_same_bss(bss, bss_info_le))
2513                                goto exit;
2514                }
2515                memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
2516                        bss_info_le, bi_length);
2517                list->version = le32_to_cpu(bss_info_le->version);
2518                list->buflen += bi_length;
2519                list->count++;
2520        } else {
2521                cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2522                if (cfg->scan_request) {
2523                        cfg->bss_list = (struct brcmf_scan_results *)
2524                                cfg->escan_info.escan_buf;
2525                        brcmf_inform_bss(cfg);
2526                        aborted = status != BRCMF_E_STATUS_SUCCESS;
2527                        brcmf_notify_escan_complete(cfg, ndev, aborted,
2528                                                    false);
2529                } else
2530                        brcmf_err("Unexpected scan result 0x%x\n", status);
2531        }
2532exit:
2533        return err;
2534}
2535
2536static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
2537{
2538        brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT,
2539                            brcmf_cfg80211_escan_handler);
2540        cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2541        /* Init scan_timeout timer */
2542        init_timer(&cfg->escan_timeout);
2543        cfg->escan_timeout.data = (unsigned long) cfg;
2544        cfg->escan_timeout.function = brcmf_escan_timeout;
2545        INIT_WORK(&cfg->escan_timeout_work,
2546                  brcmf_cfg80211_escan_timeout_worker);
2547}
2548
2549static __always_inline void brcmf_delay(u32 ms)
2550{
2551        if (ms < 1000 / HZ) {
2552                cond_resched();
2553                mdelay(ms);
2554        } else {
2555                msleep(ms);
2556        }
2557}
2558
2559static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2560{
2561        brcmf_dbg(TRACE, "Enter\n");
2562
2563        return 0;
2564}
2565
2566static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
2567                                  struct cfg80211_wowlan *wow)
2568{
2569        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2570        struct net_device *ndev = cfg_to_ndev(cfg);
2571        struct brcmf_cfg80211_vif *vif;
2572
2573        brcmf_dbg(TRACE, "Enter\n");
2574
2575        /*
2576         * if the primary net_device is not READY there is nothing
2577         * we can do but pray resume goes smoothly.
2578         */
2579        vif = ((struct brcmf_if *)netdev_priv(ndev))->vif;
2580        if (!check_vif_up(vif))
2581                goto exit;
2582
2583        list_for_each_entry(vif, &cfg->vif_list, list) {
2584                if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state))
2585                        continue;
2586                /*
2587                 * While going to suspend if associated with AP disassociate
2588                 * from AP to save power while system is in suspended state
2589                 */
2590                brcmf_link_down(vif);
2591
2592                /* Make sure WPA_Supplicant receives all the event
2593                 * generated due to DISASSOC call to the fw to keep
2594                 * the state fw and WPA_Supplicant state consistent
2595                 */
2596                brcmf_delay(500);
2597        }
2598
2599        /* end any scanning */
2600        if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
2601                brcmf_abort_scanning(cfg);
2602
2603        /* Turn off watchdog timer */
2604        brcmf_set_mpc(ndev, 1);
2605
2606exit:
2607        brcmf_dbg(TRACE, "Exit\n");
2608        /* clear any scanning activity */
2609        cfg->scan_status = 0;
2610        return 0;
2611}
2612
2613static __used s32
2614brcmf_update_pmklist(struct net_device *ndev,
2615                     struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
2616{
2617        int i, j;
2618        int pmkid_len;
2619
2620        pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
2621
2622        brcmf_dbg(CONN, "No of elements %d\n", pmkid_len);
2623        for (i = 0; i < pmkid_len; i++) {
2624                brcmf_dbg(CONN, "PMKID[%d]: %pM =\n", i,
2625                          &pmk_list->pmkids.pmkid[i].BSSID);
2626                for (j = 0; j < WLAN_PMKID_LEN; j++)
2627                        brcmf_dbg(CONN, "%02x\n",
2628                                  pmk_list->pmkids.pmkid[i].PMKID[j]);
2629        }
2630
2631        if (!err)
2632                brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
2633                                         (char *)pmk_list, sizeof(*pmk_list));
2634
2635        return err;
2636}
2637
2638static s32
2639brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2640                         struct cfg80211_pmksa *pmksa)
2641{
2642        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2643        struct brcmf_if *ifp = netdev_priv(ndev);
2644        struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
2645        s32 err = 0;
2646        int i;
2647        int pmkid_len;
2648
2649        brcmf_dbg(TRACE, "Enter\n");
2650        if (!check_vif_up(ifp->vif))
2651                return -EIO;
2652
2653        pmkid_len = le32_to_cpu(pmkids->npmkid);
2654        for (i = 0; i < pmkid_len; i++)
2655                if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2656                        break;
2657        if (i < WL_NUM_PMKIDS_MAX) {
2658                memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2659                memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2660                if (i == pmkid_len) {
2661                        pmkid_len++;
2662                        pmkids->npmkid = cpu_to_le32(pmkid_len);
2663                }
2664        } else
2665                err = -EINVAL;
2666
2667        brcmf_dbg(CONN, "set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
2668                  pmkids->pmkid[pmkid_len].BSSID);
2669        for (i = 0; i < WLAN_PMKID_LEN; i++)
2670                brcmf_dbg(CONN, "%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
2671
2672        err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
2673
2674        brcmf_dbg(TRACE, "Exit\n");
2675        return err;
2676}
2677
2678static s32
2679brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2680                      struct cfg80211_pmksa *pmksa)
2681{
2682        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2683        struct brcmf_if *ifp = netdev_priv(ndev);
2684        struct pmkid_list pmkid;
2685        s32 err = 0;
2686        int i, pmkid_len;
2687
2688        brcmf_dbg(TRACE, "Enter\n");
2689        if (!check_vif_up(ifp->vif))
2690                return -EIO;
2691
2692        memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2693        memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2694
2695        brcmf_dbg(CONN, "del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2696                  &pmkid.pmkid[0].BSSID);
2697        for (i = 0; i < WLAN_PMKID_LEN; i++)
2698                brcmf_dbg(CONN, "%02x\n", pmkid.pmkid[0].PMKID[i]);
2699
2700        pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid);
2701        for (i = 0; i < pmkid_len; i++)
2702                if (!memcmp
2703                    (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
2704                     ETH_ALEN))
2705                        break;
2706
2707        if ((pmkid_len > 0)
2708            && (i < pmkid_len)) {
2709                memset(&cfg->pmk_list->pmkids.pmkid[i], 0,
2710                       sizeof(struct pmkid));
2711                for (; i < (pmkid_len - 1); i++) {
2712                        memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
2713                               &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
2714                               ETH_ALEN);
2715                        memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
2716                               &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
2717                               WLAN_PMKID_LEN);
2718                }
2719                cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
2720        } else
2721                err = -EINVAL;
2722
2723        err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
2724
2725        brcmf_dbg(TRACE, "Exit\n");
2726        return err;
2727
2728}
2729
2730static s32
2731brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
2732{
2733        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2734        struct brcmf_if *ifp = netdev_priv(ndev);
2735        s32 err = 0;
2736
2737        brcmf_dbg(TRACE, "Enter\n");
2738        if (!check_vif_up(ifp->vif))
2739                return -EIO;
2740
2741        memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
2742        err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
2743
2744        brcmf_dbg(TRACE, "Exit\n");
2745        return err;
2746
2747}
2748
2749/*
2750 * PFN result doesn't have all the info which are
2751 * required by the supplicant
2752 * (For e.g IEs) Do a target Escan so that sched scan results are reported
2753 * via wl_inform_single_bss in the required format. Escan does require the
2754 * scan request in the form of cfg80211_scan_request. For timebeing, create
2755 * cfg80211_scan_request one out of the received PNO event.
2756 */
2757static s32
2758brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
2759                                const struct brcmf_event_msg *e, void *data)
2760{
2761        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
2762        struct net_device *ndev = ifp->ndev;
2763        struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
2764        struct cfg80211_scan_request *request = NULL;
2765        struct cfg80211_ssid *ssid = NULL;
2766        struct ieee80211_channel *channel = NULL;
2767        struct wiphy *wiphy = cfg_to_wiphy(cfg);
2768        int err = 0;
2769        int channel_req = 0;
2770        int band = 0;
2771        struct brcmf_pno_scanresults_le *pfn_result;
2772        u32 result_count;
2773        u32 status;
2774
2775        brcmf_dbg(SCAN, "Enter\n");
2776
2777        if (e->event_code == BRCMF_E_PFN_NET_LOST) {
2778                brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n");
2779                return 0;
2780        }
2781
2782        pfn_result = (struct brcmf_pno_scanresults_le *)data;
2783        result_count = le32_to_cpu(pfn_result->count);
2784        status = le32_to_cpu(pfn_result->status);
2785
2786        /*
2787         * PFN event is limited to fit 512 bytes so we may get
2788         * multiple NET_FOUND events. For now place a warning here.
2789         */
2790        WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
2791        brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
2792        if (result_count > 0) {
2793                int i;
2794
2795                request = kzalloc(sizeof(*request), GFP_KERNEL);
2796                ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
2797                channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
2798                if (!request || !ssid || !channel) {
2799                        err = -ENOMEM;
2800                        goto out_err;
2801                }
2802
2803                request->wiphy = wiphy;
2804                data += sizeof(struct brcmf_pno_scanresults_le);
2805                netinfo_start = (struct brcmf_pno_net_info_le *)data;
2806
2807                for (i = 0; i < result_count; i++) {
2808                        netinfo = &netinfo_start[i];
2809                        if (!netinfo) {
2810                                brcmf_err("Invalid netinfo ptr. index: %d\n",
2811                                          i);
2812                                err = -EINVAL;
2813                                goto out_err;
2814                        }
2815
2816                        brcmf_dbg(SCAN, "SSID:%s Channel:%d\n",
2817                                  netinfo->SSID, netinfo->channel);
2818                        memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
2819                        ssid[i].ssid_len = netinfo->SSID_len;
2820                        request->n_ssids++;
2821
2822                        channel_req = netinfo->channel;
2823                        if (channel_req <= CH_MAX_2G_CHANNEL)
2824                                band = NL80211_BAND_2GHZ;
2825                        else
2826                                band = NL80211_BAND_5GHZ;
2827                        channel[i].center_freq =
2828                                ieee80211_channel_to_frequency(channel_req,
2829                                                               band);
2830                        channel[i].band = band;
2831                        channel[i].flags |= IEEE80211_CHAN_NO_HT40;
2832                        request->channels[i] = &channel[i];
2833                        request->n_channels++;
2834                }
2835
2836                /* assign parsed ssid array */
2837                if (request->n_ssids)
2838                        request->ssids = &ssid[0];
2839
2840                if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2841                        /* Abort any on-going scan */
2842                        brcmf_abort_scanning(cfg);
2843                }
2844
2845                set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2846                err = brcmf_do_escan(cfg, wiphy, ndev, request);
2847                if (err) {
2848                        clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2849                        goto out_err;
2850                }
2851                cfg->sched_escan = true;
2852                cfg->scan_request = request;
2853        } else {
2854                brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
2855                goto out_err;
2856        }
2857
2858        kfree(ssid);
2859        kfree(channel);
2860        kfree(request);
2861        return 0;
2862
2863out_err:
2864        kfree(ssid);
2865        kfree(channel);
2866        kfree(request);
2867        cfg80211_sched_scan_stopped(wiphy);
2868        return err;
2869}
2870
2871static int brcmf_dev_pno_clean(struct net_device *ndev)
2872{
2873        int ret;
2874
2875        /* Disable pfn */
2876        ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
2877        if (ret == 0) {
2878                /* clear pfn */
2879                ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
2880                                               NULL, 0);
2881        }
2882        if (ret < 0)
2883                brcmf_err("failed code %d\n", ret);
2884
2885        return ret;
2886}
2887
2888static int brcmf_dev_pno_config(struct net_device *ndev)
2889{
2890        struct brcmf_pno_param_le pfn_param;
2891
2892        memset(&pfn_param, 0, sizeof(pfn_param));
2893        pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
2894
2895        /* set extra pno params */
2896        pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
2897        pfn_param.repeat = BRCMF_PNO_REPEAT;
2898        pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
2899
2900        /* set up pno scan fr */
2901        pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
2902
2903        return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
2904                                        &pfn_param, sizeof(pfn_param));
2905}
2906
2907static int
2908brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
2909                                struct net_device *ndev,
2910                                struct cfg80211_sched_scan_request *request)
2911{
2912        struct brcmf_if *ifp = netdev_priv(ndev);
2913        struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
2914        struct brcmf_pno_net_param_le pfn;
2915        int i;
2916        int ret = 0;
2917
2918        brcmf_dbg(SCAN, "Enter n_match_sets:%d   n_ssids:%d\n",
2919                  request->n_match_sets, request->n_ssids);
2920        if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2921                brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
2922                return -EAGAIN;
2923        }
2924
2925        if (!request || !request->n_ssids || !request->n_match_sets) {
2926                brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
2927                          request ? request->n_ssids : 0);
2928                return -EINVAL;
2929        }
2930
2931        if (request->n_ssids > 0) {
2932                for (i = 0; i < request->n_ssids; i++) {
2933                        /* Active scan req for ssids */
2934                        brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
2935                                  request->ssids[i].ssid);
2936
2937                        /*
2938                         * match_set ssids is a supert set of n_ssid list,
2939                         * so we need not add these set seperately.
2940                         */
2941                }
2942        }
2943
2944        if (request->n_match_sets > 0) {
2945                /* clean up everything */
2946                ret = brcmf_dev_pno_clean(ndev);
2947                if  (ret < 0) {
2948                        brcmf_err("failed error=%d\n", ret);
2949                        return ret;
2950                }
2951
2952                /* configure pno */
2953                ret = brcmf_dev_pno_config(ndev);
2954                if (ret < 0) {
2955                        brcmf_err("PNO setup failed!! ret=%d\n", ret);
2956                        return -EINVAL;
2957                }
2958
2959                /* configure each match set */
2960                for (i = 0; i < request->n_match_sets; i++) {
2961                        struct cfg80211_ssid *ssid;
2962                        u32 ssid_len;
2963
2964                        ssid = &request->match_sets[i].ssid;
2965                        ssid_len = ssid->ssid_len;
2966
2967                        if (!ssid_len) {
2968                                brcmf_err("skip broadcast ssid\n");
2969                                continue;
2970                        }
2971                        pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
2972                        pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
2973                        pfn.wsec = cpu_to_le32(0);
2974                        pfn.infra = cpu_to_le32(1);
2975                        pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
2976                        pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
2977                        memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
2978                        ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
2979                                                       sizeof(pfn));
2980                        brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
2981                                  ret == 0 ? "set" : "failed", ssid->ssid);
2982                }
2983                /* Enable the PNO */
2984                if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
2985                        brcmf_err("PNO enable failed!! ret=%d\n", ret);
2986                        return -EINVAL;
2987                }
2988        } else {
2989                return -EINVAL;
2990        }
2991
2992        return 0;
2993}
2994
2995static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
2996                                          struct net_device *ndev)
2997{
2998        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2999
3000        brcmf_dbg(SCAN, "enter\n");
3001        brcmf_dev_pno_clean(ndev);
3002        if (cfg->sched_escan)
3003                brcmf_notify_escan_complete(cfg, ndev, true, true);
3004        return 0;
3005}
3006
3007#ifdef CONFIG_NL80211_TESTMODE
3008static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3009{
3010        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3011        struct net_device *ndev = cfg_to_ndev(cfg);
3012        struct brcmf_dcmd *dcmd = data;
3013        struct sk_buff *reply;
3014        int ret;
3015
3016        brcmf_dbg(TRACE, "cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
3017                  dcmd->buf, dcmd->len);
3018
3019        if (dcmd->set)
3020                ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
3021                                             dcmd->buf, dcmd->len);
3022        else
3023                ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
3024                                             dcmd->buf, dcmd->len);
3025        if (ret == 0) {
3026                reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3027                nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3028                ret = cfg80211_testmode_reply(reply);
3029        }
3030        return ret;
3031}
3032#endif
3033
3034static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx)
3035{
3036        struct brcmf_if *ifp = netdev_priv(ndev);
3037        s32 err;
3038
3039        /* set auth */
3040        err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
3041        if (err < 0) {
3042                brcmf_err("auth error %d\n", err);
3043                return err;
3044        }
3045        /* set wsec */
3046        err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
3047        if (err < 0) {
3048                brcmf_err("wsec error %d\n", err);
3049                return err;
3050        }
3051        /* set upper-layer auth */
3052        err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE);
3053        if (err < 0) {
3054                brcmf_err("wpa_auth error %d\n", err);
3055                return err;
3056        }
3057
3058        return 0;
3059}
3060
3061static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
3062{
3063        if (is_rsn_ie)
3064                return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
3065
3066        return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
3067}
3068
3069static s32
3070brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
3071                     bool is_rsn_ie)
3072{
3073        struct brcmf_if *ifp = netdev_priv(ndev);
3074        u32 auth = 0; /* d11 open authentication */
3075        u16 count;
3076        s32 err = 0;
3077        s32 len = 0;
3078        u32 i;
3079        u32 wsec;
3080        u32 pval = 0;
3081        u32 gval = 0;
3082        u32 wpa_auth = 0;
3083        u32 offset;
3084        u8 *data;
3085        u16 rsn_cap;
3086        u32 wme_bss_disable;
3087
3088        brcmf_dbg(TRACE, "Enter\n");
3089        if (wpa_ie == NULL)
3090                goto exit;
3091
3092        len = wpa_ie->len + TLV_HDR_LEN;
3093        data = (u8 *)wpa_ie;
3094        offset = TLV_HDR_LEN;
3095        if (!is_rsn_ie)
3096                offset += VS_IE_FIXED_HDR_LEN;
3097        else
3098                offset += WPA_IE_VERSION_LEN;
3099
3100        /* check for multicast cipher suite */
3101        if (offset + WPA_IE_MIN_OUI_LEN > len) {
3102                err = -EINVAL;
3103                brcmf_err("no multicast cipher suite\n");
3104                goto exit;
3105        }
3106
3107        if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3108                err = -EINVAL;
3109                brcmf_err("ivalid OUI\n");
3110                goto exit;
3111        }
3112        offset += TLV_OUI_LEN;
3113
3114        /* pick up multicast cipher */
3115        switch (data[offset]) {
3116        case WPA_CIPHER_NONE:
3117                gval = 0;
3118                break;
3119        case WPA_CIPHER_WEP_40:
3120        case WPA_CIPHER_WEP_104:
3121                gval = WEP_ENABLED;
3122                break;
3123        case WPA_CIPHER_TKIP:
3124                gval = TKIP_ENABLED;
3125                break;
3126        case WPA_CIPHER_AES_CCM:
3127                gval = AES_ENABLED;
3128                break;
3129        default:
3130                err = -EINVAL;
3131                brcmf_err("Invalid multi cast cipher info\n");
3132                goto exit;
3133        }
3134
3135        offset++;
3136        /* walk thru unicast cipher list and pick up what we recognize */
3137        count = data[offset] + (data[offset + 1] << 8);
3138        offset += WPA_IE_SUITE_COUNT_LEN;
3139        /* Check for unicast suite(s) */
3140        if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3141                err = -EINVAL;
3142                brcmf_err("no unicast cipher suite\n");
3143                goto exit;
3144        }
3145        for (i = 0; i < count; i++) {
3146                if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3147                        err = -EINVAL;
3148                        brcmf_err("ivalid OUI\n");
3149                        goto exit;
3150                }
3151                offset += TLV_OUI_LEN;
3152                switch (data[offset]) {
3153                case WPA_CIPHER_NONE:
3154                        break;
3155                case WPA_CIPHER_WEP_40:
3156                case WPA_CIPHER_WEP_104:
3157                        pval |= WEP_ENABLED;
3158                        break;
3159                case WPA_CIPHER_TKIP:
3160                        pval |= TKIP_ENABLED;
3161                        break;
3162                case WPA_CIPHER_AES_CCM:
3163                        pval |= AES_ENABLED;
3164                        break;
3165                default:
3166                        brcmf_err("Ivalid unicast security info\n");
3167                }
3168                offset++;
3169        }
3170        /* walk thru auth management suite list and pick up what we recognize */
3171        count = data[offset] + (data[offset + 1] << 8);
3172        offset += WPA_IE_SUITE_COUNT_LEN;
3173        /* Check for auth key management suite(s) */
3174        if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3175                err = -EINVAL;
3176                brcmf_err("no auth key mgmt suite\n");
3177                goto exit;
3178        }
3179        for (i = 0; i < count; i++) {
3180                if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3181                        err = -EINVAL;
3182                        brcmf_err("ivalid OUI\n");
3183                        goto exit;
3184                }
3185                offset += TLV_OUI_LEN;
3186                switch (data[offset]) {
3187                case RSN_AKM_NONE:
3188                        brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
3189                        wpa_auth |= WPA_AUTH_NONE;
3190                        break;
3191                case RSN_AKM_UNSPECIFIED:
3192                        brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
3193                        is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
3194                                    (wpa_auth |= WPA_AUTH_UNSPECIFIED);
3195                        break;
3196                case RSN_AKM_PSK:
3197                        brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
3198                        is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
3199                                    (wpa_auth |= WPA_AUTH_PSK);
3200                        break;
3201                default:
3202                        brcmf_err("Ivalid key mgmt info\n");
3203                }
3204                offset++;
3205        }
3206
3207        if (is_rsn_ie) {
3208                wme_bss_disable = 1;
3209                if ((offset + RSN_CAP_LEN) <= len) {
3210                        rsn_cap = data[offset] + (data[offset + 1] << 8);
3211                        if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
3212                                wme_bss_disable = 0;
3213                }
3214                /* set wme_bss_disable to sync RSN Capabilities */
3215                err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
3216                                               wme_bss_disable);
3217                if (err < 0) {
3218                        brcmf_err("wme_bss_disable error %d\n", err);
3219                        goto exit;
3220                }
3221        }
3222        /* FOR WPS , set SES_OW_ENABLED */
3223        wsec = (pval | gval | SES_OW_ENABLED);
3224
3225        /* set auth */
3226        err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
3227        if (err < 0) {
3228                brcmf_err("auth error %d\n", err);
3229                goto exit;
3230        }
3231        /* set wsec */
3232        err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
3233        if (err < 0) {
3234                brcmf_err("wsec error %d\n", err);
3235                goto exit;
3236        }
3237        /* set upper-layer auth */
3238        err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
3239        if (err < 0) {
3240                brcmf_err("wpa_auth error %d\n", err);
3241                goto exit;
3242        }
3243
3244exit:
3245        return err;
3246}
3247
3248static s32
3249brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
3250                     struct parsed_vndr_ies *vndr_ies)
3251{
3252        s32 err = 0;
3253        struct brcmf_vs_tlv *vndrie;
3254        struct brcmf_tlv *ie;
3255        struct parsed_vndr_ie_info *parsed_info;
3256        s32 remaining_len;
3257
3258        remaining_len = (s32)vndr_ie_len;
3259        memset(vndr_ies, 0, sizeof(*vndr_ies));
3260
3261        ie = (struct brcmf_tlv *)vndr_ie_buf;
3262        while (ie) {
3263                if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
3264                        goto next;
3265                vndrie = (struct brcmf_vs_tlv *)ie;
3266                /* len should be bigger than OUI length + one */
3267                if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
3268                        brcmf_err("invalid vndr ie. length is too small %d\n",
3269                                  vndrie->len);
3270                        goto next;
3271                }
3272                /* if wpa or wme ie, do not add ie */
3273                if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
3274                    ((vndrie->oui_type == WPA_OUI_TYPE) ||
3275                    (vndrie->oui_type == WME_OUI_TYPE))) {
3276                        brcmf_dbg(TRACE, "Found WPA/WME oui. Do not add it\n");
3277                        goto next;
3278                }
3279
3280                parsed_info = &vndr_ies->ie_info[vndr_ies->count];
3281
3282                /* save vndr ie information */
3283                parsed_info->ie_ptr = (char *)vndrie;
3284                parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
3285                memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
3286
3287                vndr_ies->count++;
3288
3289                brcmf_dbg(TRACE, "** OUI %02x %02x %02x, type 0x%02x\n",
3290                          parsed_info->vndrie.oui[0],
3291                          parsed_info->vndrie.oui[1],
3292                          parsed_info->vndrie.oui[2],
3293                          parsed_info->vndrie.oui_type);
3294
3295                if (vndr_ies->count >= MAX_VNDR_IE_NUMBER)
3296                        break;
3297next:
3298                remaining_len -= (ie->len + TLV_HDR_LEN);
3299                if (remaining_len <= TLV_HDR_LEN)
3300                        ie = NULL;
3301                else
3302                        ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
3303                                TLV_HDR_LEN);
3304        }
3305        return err;
3306}
3307
3308static u32
3309brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
3310{
3311
3312        __le32 iecount_le;
3313        __le32 pktflag_le;
3314
3315        strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
3316        iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
3317
3318        iecount_le = cpu_to_le32(1);
3319        memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le));
3320
3321        pktflag_le = cpu_to_le32(pktflag);
3322        memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le));
3323
3324        memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
3325
3326        return ie_len + VNDR_IE_HDR_SIZE;
3327}
3328
3329static
3330s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
3331                          const u8 *vndr_ie_buf, u32 vndr_ie_len)
3332{
3333        struct brcmf_if *ifp;
3334        struct vif_saved_ie *saved_ie;
3335        s32 err = 0;
3336        u8  *iovar_ie_buf;
3337        u8  *curr_ie_buf;
3338        u8  *mgmt_ie_buf = NULL;
3339        int mgmt_ie_buf_len;
3340        u32 *mgmt_ie_len;
3341        u32 del_add_ie_buf_len = 0;
3342        u32 total_ie_buf_len = 0;
3343        u32 parsed_ie_buf_len = 0;
3344        struct parsed_vndr_ies old_vndr_ies;
3345        struct parsed_vndr_ies new_vndr_ies;
3346        struct parsed_vndr_ie_info *vndrie_info;
3347        s32 i;
3348        u8 *ptr;
3349        int remained_buf_len;
3350
3351        if (!vif)
3352                return -ENODEV;
3353        ifp = vif->ifp;
3354        saved_ie = &vif->saved_ie;
3355
3356        brcmf_dbg(TRACE, "bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag);
3357        iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3358        if (!iovar_ie_buf)
3359                return -ENOMEM;
3360        curr_ie_buf = iovar_ie_buf;
3361        if (ifp->vif->mode == WL_MODE_AP) {
3362                switch (pktflag) {
3363                case VNDR_IE_PRBRSP_FLAG:
3364                        mgmt_ie_buf = saved_ie->probe_res_ie;
3365                        mgmt_ie_len = &saved_ie->probe_res_ie_len;
3366                        mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
3367                        break;
3368                case VNDR_IE_BEACON_FLAG:
3369                        mgmt_ie_buf = saved_ie->beacon_ie;
3370                        mgmt_ie_len = &saved_ie->beacon_ie_len;
3371                        mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);
3372                        break;
3373                default:
3374                        err = -EPERM;
3375                        brcmf_err("not suitable type\n");
3376                        goto exit;
3377                }
3378        } else {
3379                err = -EPERM;
3380                brcmf_err("not suitable type\n");
3381                goto exit;
3382        }
3383
3384        if (vndr_ie_len > mgmt_ie_buf_len) {
3385                err = -ENOMEM;
3386                brcmf_err("extra IE size too big\n");
3387                goto exit;
3388        }
3389
3390        /* parse and save new vndr_ie in curr_ie_buff before comparing it */
3391        if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {
3392                ptr = curr_ie_buf;
3393                brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);
3394                for (i = 0; i < new_vndr_ies.count; i++) {
3395                        vndrie_info = &new_vndr_ies.ie_info[i];
3396                        memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
3397                               vndrie_info->ie_len);
3398                        parsed_ie_buf_len += vndrie_info->ie_len;
3399                }
3400        }
3401
3402        if (mgmt_ie_buf && *mgmt_ie_len) {
3403                if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
3404                    (memcmp(mgmt_ie_buf, curr_ie_buf,
3405                            parsed_ie_buf_len) == 0)) {
3406                        brcmf_dbg(TRACE, "Previous mgmt IE equals to current IE\n");
3407                        goto exit;
3408                }
3409
3410                /* parse old vndr_ie */
3411                brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);
3412
3413                /* make a command to delete old ie */
3414                for (i = 0; i < old_vndr_ies.count; i++) {
3415                        vndrie_info = &old_vndr_ies.ie_info[i];
3416
3417                        brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
3418                                  vndrie_info->vndrie.id,
3419                                  vndrie_info->vndrie.len,
3420                                  vndrie_info->vndrie.oui[0],
3421                                  vndrie_info->vndrie.oui[1],
3422                                  vndrie_info->vndrie.oui[2]);
3423
3424                        del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3425                                                           vndrie_info->ie_ptr,
3426                                                           vndrie_info->ie_len,
3427                                                           "del");
3428                        curr_ie_buf += del_add_ie_buf_len;
3429                        total_ie_buf_len += del_add_ie_buf_len;
3430                }
3431        }
3432
3433        *mgmt_ie_len = 0;
3434        /* Add if there is any extra IE */
3435        if (mgmt_ie_buf && parsed_ie_buf_len) {
3436                ptr = mgmt_ie_buf;
3437
3438                remained_buf_len = mgmt_ie_buf_len;
3439
3440                /* make a command to add new ie */
3441                for (i = 0; i < new_vndr_ies.count; i++) {
3442                        vndrie_info = &new_vndr_ies.ie_info[i];
3443
3444                        /* verify remained buf size before copy data */
3445                        if (remained_buf_len < (vndrie_info->vndrie.len +
3446                                                        VNDR_IE_VSIE_OFFSET)) {
3447                                brcmf_err("no space in mgmt_ie_buf: len left %d",
3448                                          remained_buf_len);
3449                                break;
3450                        }
3451                        remained_buf_len -= (vndrie_info->ie_len +
3452                                             VNDR_IE_VSIE_OFFSET);
3453
3454                        brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
3455                                  vndrie_info->vndrie.id,
3456                                  vndrie_info->vndrie.len,
3457                                  vndrie_info->vndrie.oui[0],
3458                                  vndrie_info->vndrie.oui[1],
3459                                  vndrie_info->vndrie.oui[2]);
3460
3461                        del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3462                                                           vndrie_info->ie_ptr,
3463                                                           vndrie_info->ie_len,
3464                                                           "add");
3465
3466                        /* save the parsed IE in wl struct */
3467                        memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
3468                               vndrie_info->ie_len);
3469                        *mgmt_ie_len += vndrie_info->ie_len;
3470
3471                        curr_ie_buf += del_add_ie_buf_len;
3472                        total_ie_buf_len += del_add_ie_buf_len;
3473                }
3474        }
3475        if (total_ie_buf_len) {
3476                err  = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
3477                                                 total_ie_buf_len);
3478                if (err)
3479                        brcmf_err("vndr ie set error : %d\n", err);
3480        }
3481
3482exit:
3483        kfree(iovar_ie_buf);
3484        return err;
3485}
3486
3487static s32
3488brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
3489                        struct cfg80211_ap_settings *settings)
3490{
3491        s32 ie_offset;
3492        struct brcmf_if *ifp = netdev_priv(ndev);
3493        struct brcmf_tlv *ssid_ie;
3494        struct brcmf_ssid_le ssid_le;
3495        s32 err = -EPERM;
3496        struct brcmf_tlv *rsn_ie;
3497        struct brcmf_vs_tlv *wpa_ie;
3498        struct brcmf_join_params join_params;
3499        s32 bssidx = 0;
3500
3501        brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
3502                  cfg80211_get_chandef_type(&settings->chandef),
3503                  settings->beacon_interval,
3504                  settings->dtim_period);
3505        brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
3506                  settings->ssid, settings->ssid_len, settings->auth_type,
3507                  settings->inactivity_timeout);
3508
3509        if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) {
3510                brcmf_err("Not in AP creation mode\n");
3511                return -EPERM;
3512        }
3513
3514        memset(&ssid_le, 0, sizeof(ssid_le));
3515        if (settings->ssid == NULL || settings->ssid_len == 0) {
3516                ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
3517                ssid_ie = brcmf_parse_tlvs(
3518                                (u8 *)&settings->beacon.head[ie_offset],
3519                                settings->beacon.head_len - ie_offset,
3520                                WLAN_EID_SSID);
3521                if (!ssid_ie)
3522                        return -EINVAL;
3523
3524                memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
3525                ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
3526                brcmf_dbg(TRACE, "SSID is (%s) in Head\n", ssid_le.SSID);
3527        } else {
3528                memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
3529                ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
3530        }
3531
3532        brcmf_set_mpc(ndev, 0);
3533        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
3534        if (err < 0) {
3535                brcmf_err("BRCMF_C_DOWN error %d\n", err);
3536                goto exit;
3537        }
3538        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
3539        if (err < 0) {
3540                brcmf_err("SET INFRA error %d\n", err);
3541                goto exit;
3542        }
3543        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
3544        if (err < 0) {
3545                brcmf_err("setting AP mode failed %d\n", err);
3546                goto exit;
3547        }
3548
3549        /* find the RSN_IE */
3550        rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
3551                                  settings->beacon.tail_len, WLAN_EID_RSN);
3552
3553        /* find the WPA_IE */
3554        wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
3555                                  settings->beacon.tail_len);
3556
3557        if ((wpa_ie != NULL || rsn_ie != NULL)) {
3558                brcmf_dbg(TRACE, "WPA(2) IE is found\n");
3559                if (wpa_ie != NULL) {
3560                        /* WPA IE */
3561                        err = brcmf_configure_wpaie(ndev, wpa_ie, false);
3562                        if (err < 0)
3563                                goto exit;
3564                } else {
3565                        /* RSN IE */
3566                        err = brcmf_configure_wpaie(ndev,
3567                                (struct brcmf_vs_tlv *)rsn_ie, true);
3568                        if (err < 0)
3569                                goto exit;
3570                }
3571        } else {
3572                brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
3573                brcmf_configure_opensecurity(ndev, bssidx);
3574        }
3575        /* Set Beacon IEs to FW */
3576        err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev),
3577                                    VNDR_IE_BEACON_FLAG,
3578                                    settings->beacon.tail,
3579                                    settings->beacon.tail_len);
3580        if (err)
3581                brcmf_err("Set Beacon IE Failed\n");
3582        else
3583                brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");
3584
3585        /* Set Probe Response IEs to FW */
3586        err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev),
3587                                    VNDR_IE_PRBRSP_FLAG,
3588                                    settings->beacon.proberesp_ies,
3589                                    settings->beacon.proberesp_ies_len);
3590        if (err)
3591                brcmf_err("Set Probe Resp IE Failed\n");
3592        else
3593                brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");
3594
3595        if (settings->beacon_interval) {
3596                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
3597                                            settings->beacon_interval);
3598                if (err < 0) {
3599                        brcmf_err("Beacon Interval Set Error, %d\n", err);
3600                        goto exit;
3601                }
3602        }
3603        if (settings->dtim_period) {
3604                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
3605                                            settings->dtim_period);
3606                if (err < 0) {
3607                        brcmf_err("DTIM Interval Set Error, %d\n", err);
3608                        goto exit;
3609                }
3610        }
3611        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
3612        if (err < 0) {
3613                brcmf_err("BRCMF_C_UP error (%d)\n", err);
3614                goto exit;
3615        }
3616
3617        memset(&join_params, 0, sizeof(join_params));
3618        /* join parameters starts with ssid */
3619        memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
3620        /* create softap */
3621        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
3622                                     &join_params, sizeof(join_params));
3623        if (err < 0) {
3624                brcmf_err("SET SSID error (%d)\n", err);
3625                goto exit;
3626        }
3627        clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
3628        set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
3629
3630exit:
3631        if (err)
3632                brcmf_set_mpc(ndev, 1);
3633        return err;
3634}
3635
3636static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
3637{
3638        struct brcmf_if *ifp = netdev_priv(ndev);
3639        s32 err = -EPERM;
3640
3641        brcmf_dbg(TRACE, "Enter\n");
3642
3643        if (ifp->vif->mode == WL_MODE_AP) {
3644                /* Due to most likely deauths outstanding we sleep */
3645                /* first to make sure they get processed by fw. */
3646                msleep(400);
3647                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
3648                if (err < 0) {
3649                        brcmf_err("setting AP mode failed %d\n", err);
3650                        goto exit;
3651                }
3652                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
3653                if (err < 0) {
3654                        brcmf_err("BRCMF_C_UP error %d\n", err);
3655                        goto exit;
3656                }
3657                brcmf_set_mpc(ndev, 1);
3658                clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
3659                clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
3660        }
3661exit:
3662        return err;
3663}
3664
3665static int
3666brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
3667                           u8 *mac)
3668{
3669        struct brcmf_scb_val_le scbval;
3670        struct brcmf_if *ifp = netdev_priv(ndev);
3671        s32 err;
3672
3673        if (!mac)
3674                return -EFAULT;
3675
3676        brcmf_dbg(TRACE, "Enter %pM\n", mac);
3677
3678        if (!check_vif_up(ifp->vif))
3679                return -EIO;
3680
3681        memcpy(&scbval.ea, mac, ETH_ALEN);
3682        scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
3683        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
3684                                     &scbval, sizeof(scbval));
3685        if (err)
3686                brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
3687
3688        brcmf_dbg(TRACE, "Exit\n");
3689        return err;
3690}
3691
3692static struct cfg80211_ops wl_cfg80211_ops = {
3693        .change_virtual_intf = brcmf_cfg80211_change_iface,
3694        .scan = brcmf_cfg80211_scan,
3695        .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
3696        .join_ibss = brcmf_cfg80211_join_ibss,
3697        .leave_ibss = brcmf_cfg80211_leave_ibss,
3698        .get_station = brcmf_cfg80211_get_station,
3699        .set_tx_power = brcmf_cfg80211_set_tx_power,
3700        .get_tx_power = brcmf_cfg80211_get_tx_power,
3701        .add_key = brcmf_cfg80211_add_key,
3702        .del_key = brcmf_cfg80211_del_key,
3703        .get_key = brcmf_cfg80211_get_key,
3704        .set_default_key = brcmf_cfg80211_config_default_key,
3705        .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
3706        .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
3707        .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
3708        .connect = brcmf_cfg80211_connect,
3709        .disconnect = brcmf_cfg80211_disconnect,
3710        .suspend = brcmf_cfg80211_suspend,
3711        .resume = brcmf_cfg80211_resume,
3712        .set_pmksa = brcmf_cfg80211_set_pmksa,
3713        .del_pmksa = brcmf_cfg80211_del_pmksa,
3714        .flush_pmksa = brcmf_cfg80211_flush_pmksa,
3715        .start_ap = brcmf_cfg80211_start_ap,
3716        .stop_ap = brcmf_cfg80211_stop_ap,
3717        .del_station = brcmf_cfg80211_del_station,
3718        .sched_scan_start = brcmf_cfg80211_sched_scan_start,
3719        .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
3720#ifdef CONFIG_NL80211_TESTMODE
3721        .testmode_cmd = brcmf_cfg80211_testmode
3722#endif
3723};
3724
3725static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
3726{
3727        s32 err = 0;
3728
3729        switch (mode) {
3730        case WL_MODE_BSS:
3731                return NL80211_IFTYPE_STATION;
3732        case WL_MODE_IBSS:
3733                return NL80211_IFTYPE_ADHOC;
3734        default:
3735                return NL80211_IFTYPE_UNSPECIFIED;
3736        }
3737
3738        return err;
3739}
3740
3741static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
3742{
3743        /* scheduled scan settings */
3744        wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
3745        wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
3746        wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
3747        wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3748}
3749
3750static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
3751{
3752        struct wiphy *wiphy;
3753        s32 err = 0;
3754
3755        wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
3756        if (!wiphy) {
3757                brcmf_err("Could not allocate wiphy device\n");
3758                return ERR_PTR(-ENOMEM);
3759        }
3760        set_wiphy_dev(wiphy, phydev);
3761        wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
3762        wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
3763        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3764                                 BIT(NL80211_IFTYPE_ADHOC) |
3765                                 BIT(NL80211_IFTYPE_AP);
3766        wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
3767        wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;  /* Set
3768                                                * it as 11a by default.
3769                                                * This will be updated with
3770                                                * 11n phy tables in
3771                                                * "ifconfig up"
3772                                                * if phy has 11n capability
3773                                                */
3774        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3775        wiphy->cipher_suites = __wl_cipher_suites;
3776        wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
3777        wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;    /* enable power
3778                                                                 * save mode
3779                                                                 * by default
3780                                                                 */
3781        brcmf_wiphy_pno_params(wiphy);
3782        err = wiphy_register(wiphy);
3783        if (err < 0) {
3784                brcmf_err("Could not register wiphy device (%d)\n", err);
3785                wiphy_free(wiphy);
3786                return ERR_PTR(err);
3787        }
3788        return wiphy;
3789}
3790
3791static
3792struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
3793                                           struct net_device *netdev,
3794                                           s32 mode, bool pm_block)
3795{
3796        struct brcmf_cfg80211_vif *vif;
3797
3798        if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
3799                return ERR_PTR(-ENOSPC);
3800
3801        vif = kzalloc(sizeof(*vif), GFP_KERNEL);
3802        if (!vif)
3803                return ERR_PTR(-ENOMEM);
3804
3805        vif->wdev.wiphy = cfg->wiphy;
3806        vif->wdev.netdev = netdev;
3807        vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
3808
3809        if (netdev) {
3810                vif->ifp = netdev_priv(netdev);
3811                netdev->ieee80211_ptr = &vif->wdev;
3812                SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy));
3813        }
3814
3815        vif->mode = mode;
3816        vif->pm_block = pm_block;
3817        vif->roam_off = -1;
3818
3819        brcmf_init_prof(&vif->profile);
3820
3821        list_add_tail(&vif->list, &cfg->vif_list);
3822        cfg->vif_cnt++;
3823        return vif;
3824}
3825
3826static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
3827{
3828        struct brcmf_cfg80211_info *cfg;
3829        struct wiphy *wiphy;
3830
3831        wiphy = vif->wdev.wiphy;
3832        cfg = wiphy_priv(wiphy);
3833        list_del(&vif->list);
3834        cfg->vif_cnt--;
3835
3836        kfree(vif);
3837        if (!cfg->vif_cnt) {
3838                wiphy_unregister(wiphy);
3839                wiphy_free(wiphy);
3840        }
3841}
3842
3843static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
3844{
3845        u32 event = e->event_code;
3846        u32 status = e->status;
3847
3848        if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
3849                brcmf_dbg(CONN, "Processing set ssid\n");
3850                return true;
3851        }
3852
3853        return false;
3854}
3855
3856static bool brcmf_is_linkdown(const struct brcmf_event_msg *e)
3857{
3858        u32 event = e->event_code;
3859        u16 flags = e->flags;
3860
3861        if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
3862                brcmf_dbg(CONN, "Processing link down\n");
3863                return true;
3864        }
3865        return false;
3866}
3867
3868static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
3869                               const struct brcmf_event_msg *e)
3870{
3871        u32 event = e->event_code;
3872        u32 status = e->status;
3873
3874        if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
3875                brcmf_dbg(CONN, "Processing Link %s & no network found\n",
3876                          e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");
3877                return true;
3878        }
3879
3880        if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
3881                brcmf_dbg(CONN, "Processing connecting & no network found\n");
3882                return true;
3883        }
3884
3885        return false;
3886}
3887
3888static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
3889{
3890        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
3891
3892        kfree(conn_info->req_ie);
3893        conn_info->req_ie = NULL;
3894        conn_info->req_ie_len = 0;
3895        kfree(conn_info->resp_ie);
3896        conn_info->resp_ie = NULL;
3897        conn_info->resp_ie_len = 0;
3898}
3899
3900static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
3901{
3902        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
3903        struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
3904        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
3905        u32 req_len;
3906        u32 resp_len;
3907        s32 err = 0;
3908
3909        brcmf_clear_assoc_ies(cfg);
3910
3911        err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
3912                                       cfg->extra_buf, WL_ASSOC_INFO_MAX);
3913        if (err) {
3914                brcmf_err("could not get assoc info (%d)\n", err);
3915                return err;
3916        }
3917        assoc_info =
3918                (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
3919        req_len = le32_to_cpu(assoc_info->req_len);
3920        resp_len = le32_to_cpu(assoc_info->resp_len);
3921        if (req_len) {
3922                err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
3923                                               cfg->extra_buf,
3924                                               WL_ASSOC_INFO_MAX);
3925                if (err) {
3926                        brcmf_err("could not get assoc req (%d)\n", err);
3927                        return err;
3928                }
3929                conn_info->req_ie_len = req_len;
3930                conn_info->req_ie =
3931                    kmemdup(cfg->extra_buf, conn_info->req_ie_len,
3932                            GFP_KERNEL);
3933        } else {
3934                conn_info->req_ie_len = 0;
3935                conn_info->req_ie = NULL;
3936        }
3937        if (resp_len) {
3938                err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
3939                                               cfg->extra_buf,
3940                                               WL_ASSOC_INFO_MAX);
3941                if (err) {
3942                        brcmf_err("could not get assoc resp (%d)\n", err);
3943                        return err;
3944                }
3945                conn_info->resp_ie_len = resp_len;
3946                conn_info->resp_ie =
3947                    kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
3948                            GFP_KERNEL);
3949        } else {
3950                conn_info->resp_ie_len = 0;
3951                conn_info->resp_ie = NULL;
3952        }
3953        brcmf_dbg(CONN, "req len (%d) resp len (%d)\n",
3954                  conn_info->req_ie_len, conn_info->resp_ie_len);
3955
3956        return err;
3957}
3958
3959static s32
3960brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
3961                       struct net_device *ndev,
3962                       const struct brcmf_event_msg *e)
3963{
3964        struct brcmf_if *ifp = netdev_priv(ndev);
3965        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
3966        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
3967        struct wiphy *wiphy = cfg_to_wiphy(cfg);
3968        struct ieee80211_channel *notify_channel = NULL;
3969        struct ieee80211_supported_band *band;
3970        struct brcmf_bss_info_le *bi;
3971        u32 freq;
3972        s32 err = 0;
3973        u32 target_channel;
3974        u8 *buf;
3975
3976        brcmf_dbg(TRACE, "Enter\n");
3977
3978        brcmf_get_assoc_ies(cfg);
3979        memcpy(profile->bssid, e->addr, ETH_ALEN);
3980        brcmf_update_bss_info(cfg);
3981
3982        buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3983        if (buf == NULL) {
3984                err = -ENOMEM;
3985                goto done;
3986        }
3987
3988        /* data sent to dongle has to be little endian */
3989        *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
3990        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
3991                                     buf, WL_BSS_INFO_MAX);
3992
3993        if (err)
3994                goto done;
3995
3996        bi = (struct brcmf_bss_info_le *)(buf + 4);
3997        target_channel = bi->ctl_ch ? bi->ctl_ch :
3998                                      CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
3999
4000        if (target_channel <= CH_MAX_2G_CHANNEL)
4001                band = wiphy->bands[IEEE80211_BAND_2GHZ];
4002        else
4003                band = wiphy->bands[IEEE80211_BAND_5GHZ];
4004
4005        freq = ieee80211_channel_to_frequency(target_channel, band->band);
4006        notify_channel = ieee80211_get_channel(wiphy, freq);
4007
4008done:
4009        kfree(buf);
4010        cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
4011                        conn_info->req_ie, conn_info->req_ie_len,
4012                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
4013        brcmf_dbg(CONN, "Report roaming result\n");
4014
4015        set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
4016        brcmf_dbg(TRACE, "Exit\n");
4017        return err;
4018}
4019
4020static s32
4021brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
4022                       struct net_device *ndev, const struct brcmf_event_msg *e,
4023                       bool completed)
4024{
4025        struct brcmf_if *ifp = netdev_priv(ndev);
4026        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4027        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4028        s32 err = 0;
4029
4030        brcmf_dbg(TRACE, "Enter\n");
4031
4032        if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4033                               &ifp->vif->sme_state)) {
4034                if (completed) {
4035                        brcmf_get_assoc_ies(cfg);
4036                        memcpy(profile->bssid, e->addr, ETH_ALEN);
4037                        brcmf_update_bss_info(cfg);
4038                }
4039                cfg80211_connect_result(ndev,
4040                                        (u8 *)profile->bssid,
4041                                        conn_info->req_ie,
4042                                        conn_info->req_ie_len,
4043                                        conn_info->resp_ie,
4044                                        conn_info->resp_ie_len,
4045                                        completed ? WLAN_STATUS_SUCCESS :
4046                                                    WLAN_STATUS_AUTH_TIMEOUT,
4047                                        GFP_KERNEL);
4048                if (completed)
4049                        set_bit(BRCMF_VIF_STATUS_CONNECTED,
4050                                &ifp->vif->sme_state);
4051                brcmf_dbg(CONN, "Report connect result - connection %s\n",
4052                          completed ? "succeeded" : "failed");
4053        }
4054        brcmf_dbg(TRACE, "Exit\n");
4055        return err;
4056}
4057
4058static s32
4059brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
4060                               struct net_device *ndev,
4061                               const struct brcmf_event_msg *e, void *data)
4062{
4063        s32 err = 0;
4064        u32 event = e->event_code;
4065        u32 reason = e->reason;
4066        u32 len = e->datalen;
4067        static int generation;
4068
4069        struct station_info sinfo;
4070
4071        brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
4072        memset(&sinfo, 0, sizeof(sinfo));
4073
4074        sinfo.filled = 0;
4075        if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
4076            reason == BRCMF_E_STATUS_SUCCESS) {
4077                sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
4078                if (!data) {
4079                        brcmf_err("No IEs present in ASSOC/REASSOC_IND");
4080                        return -EINVAL;
4081                }
4082                sinfo.assoc_req_ies = data;
4083                sinfo.assoc_req_ies_len = len;
4084                generation++;
4085                sinfo.generation = generation;
4086                cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_ATOMIC);
4087        } else if ((event == BRCMF_E_DISASSOC_IND) ||
4088                   (event == BRCMF_E_DEAUTH_IND) ||
4089                   (event == BRCMF_E_DEAUTH)) {
4090                generation++;
4091                sinfo.generation = generation;
4092                cfg80211_del_sta(ndev, e->addr, GFP_ATOMIC);
4093        }
4094        return err;
4095}
4096
4097static s32
4098brcmf_notify_connect_status(struct brcmf_if *ifp,
4099                            const struct brcmf_event_msg *e, void *data)
4100{
4101        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4102        struct net_device *ndev = ifp->ndev;
4103        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4104        s32 err = 0;
4105
4106        if (ifp->vif->mode == WL_MODE_AP) {
4107                err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
4108        } else if (brcmf_is_linkup(e)) {
4109                brcmf_dbg(CONN, "Linkup\n");
4110                if (brcmf_is_ibssmode(ifp->vif)) {
4111                        memcpy(profile->bssid, e->addr, ETH_ALEN);
4112                        wl_inform_ibss(cfg, ndev, e->addr);
4113                        cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
4114                        clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4115                                  &ifp->vif->sme_state);
4116                        set_bit(BRCMF_VIF_STATUS_CONNECTED,
4117                                &ifp->vif->sme_state);
4118                } else
4119                        brcmf_bss_connect_done(cfg, ndev, e, true);
4120        } else if (brcmf_is_linkdown(e)) {
4121                brcmf_dbg(CONN, "Linkdown\n");
4122                if (!brcmf_is_ibssmode(ifp->vif)) {
4123                        brcmf_bss_connect_done(cfg, ndev, e, false);
4124                        if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
4125                                               &ifp->vif->sme_state))
4126                                cfg80211_disconnected(ndev, 0, NULL, 0,
4127                                                      GFP_KERNEL);
4128                }
4129                brcmf_link_down(ifp->vif);
4130                brcmf_init_prof(ndev_to_prof(ndev));
4131        } else if (brcmf_is_nonetwork(cfg, e)) {
4132                if (brcmf_is_ibssmode(ifp->vif))
4133                        clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4134                                  &ifp->vif->sme_state);
4135                else
4136                        brcmf_bss_connect_done(cfg, ndev, e, false);
4137        }
4138
4139        return err;
4140}
4141
4142static s32
4143brcmf_notify_roaming_status(struct brcmf_if *ifp,
4144                            const struct brcmf_event_msg *e, void *data)
4145{
4146        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4147        s32 err = 0;
4148        u32 event = e->event_code;
4149        u32 status = e->status;
4150
4151        if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
4152                if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
4153                        brcmf_bss_roaming_done(cfg, ifp->ndev, e);
4154                else
4155                        brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
4156        }
4157
4158        return err;
4159}
4160
4161static s32
4162brcmf_notify_mic_status(struct brcmf_if *ifp,
4163                        const struct brcmf_event_msg *e, void *data)
4164{
4165        u16 flags = e->flags;
4166        enum nl80211_key_type key_type;
4167
4168        if (flags & BRCMF_EVENT_MSG_GROUP)
4169                key_type = NL80211_KEYTYPE_GROUP;
4170        else
4171                key_type = NL80211_KEYTYPE_PAIRWISE;
4172
4173        cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
4174                                     NULL, GFP_KERNEL);
4175
4176        return 0;
4177}
4178
4179static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
4180{
4181        conf->frag_threshold = (u32)-1;
4182        conf->rts_threshold = (u32)-1;
4183        conf->retry_short = (u32)-1;
4184        conf->retry_long = (u32)-1;
4185        conf->tx_power = -1;
4186}
4187
4188static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
4189{
4190        brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,
4191                            brcmf_notify_connect_status);
4192        brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,
4193                            brcmf_notify_connect_status);
4194        brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,
4195                            brcmf_notify_connect_status);
4196        brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,
4197                            brcmf_notify_connect_status);
4198        brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,
4199                            brcmf_notify_connect_status);
4200        brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,
4201                            brcmf_notify_connect_status);
4202        brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,
4203                            brcmf_notify_roaming_status);
4204        brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,
4205                            brcmf_notify_mic_status);
4206        brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,
4207                            brcmf_notify_connect_status);
4208        brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
4209                            brcmf_notify_sched_scan_results);
4210}
4211
4212static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
4213{
4214        kfree(cfg->conf);
4215        cfg->conf = NULL;
4216        kfree(cfg->escan_ioctl_buf);
4217        cfg->escan_ioctl_buf = NULL;
4218        kfree(cfg->extra_buf);
4219        cfg->extra_buf = NULL;
4220        kfree(cfg->pmk_list);
4221        cfg->pmk_list = NULL;
4222}
4223
4224static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
4225{
4226        cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
4227        if (!cfg->conf)
4228                goto init_priv_mem_out;
4229        cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4230        if (!cfg->escan_ioctl_buf)
4231                goto init_priv_mem_out;
4232        cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
4233        if (!cfg->extra_buf)
4234                goto init_priv_mem_out;
4235        cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
4236        if (!cfg->pmk_list)
4237                goto init_priv_mem_out;
4238
4239        return 0;
4240
4241init_priv_mem_out:
4242        brcmf_deinit_priv_mem(cfg);
4243
4244        return -ENOMEM;
4245}
4246
4247static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
4248{
4249        s32 err = 0;
4250
4251        cfg->scan_request = NULL;
4252        cfg->pwr_save = true;
4253        cfg->roam_on = true;    /* roam on & off switch.
4254                                 we enable roam per default */
4255        cfg->active_scan = true;        /* we do active scan for
4256                                 specific scan per default */
4257        cfg->dongle_up = false; /* dongle is not up yet */
4258        err = brcmf_init_priv_mem(cfg);
4259        if (err)
4260                return err;
4261        brcmf_register_event_handlers(cfg);
4262        mutex_init(&cfg->usr_sync);
4263        brcmf_init_escan(cfg);
4264        brcmf_init_conf(cfg->conf);
4265
4266        return err;
4267}
4268
4269static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
4270{
4271        cfg->dongle_up = false; /* dongle down */
4272        brcmf_abort_scanning(cfg);
4273        brcmf_deinit_priv_mem(cfg);
4274}
4275
4276struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
4277                                                  struct device *busdev)
4278{
4279        struct net_device *ndev = drvr->iflist[0]->ndev;
4280        struct brcmf_cfg80211_info *cfg;
4281        struct wiphy *wiphy;
4282        struct brcmf_cfg80211_vif *vif;
4283        struct brcmf_if *ifp;
4284        s32 err = 0;
4285
4286        if (!ndev) {
4287                brcmf_err("ndev is invalid\n");
4288                return NULL;
4289        }
4290
4291        ifp = netdev_priv(ndev);
4292        wiphy = brcmf_setup_wiphy(busdev);
4293        if (IS_ERR(wiphy))
4294                return NULL;
4295
4296        cfg = wiphy_priv(wiphy);
4297        cfg->wiphy = wiphy;
4298        cfg->pub = drvr;
4299        INIT_LIST_HEAD(&cfg->vif_list);
4300
4301        vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false);
4302        if (IS_ERR(vif)) {
4303                wiphy_free(wiphy);
4304                return NULL;
4305        }
4306
4307        err = wl_init_priv(cfg);
4308        if (err) {
4309                brcmf_err("Failed to init iwm_priv (%d)\n", err);
4310                goto cfg80211_attach_out;
4311        }
4312
4313        ifp->vif = vif;
4314        return cfg;
4315
4316cfg80211_attach_out:
4317        brcmf_free_vif(vif);
4318        return NULL;
4319}
4320
4321void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
4322{
4323        struct brcmf_cfg80211_vif *vif;
4324        struct brcmf_cfg80211_vif *tmp;
4325
4326        wl_deinit_priv(cfg);
4327        list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
4328                brcmf_free_vif(vif);
4329        }
4330}
4331
4332static s32
4333brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
4334{
4335        struct brcmf_if *ifp = netdev_priv(ndev);
4336        s32 err = 0;
4337        __le32 roamtrigger[2];
4338        __le32 roam_delta[2];
4339
4340        /*
4341         * Setup timeout if Beacons are lost and roam is
4342         * off to report link down
4343         */
4344        if (roamvar) {
4345                err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
4346                if (err) {
4347                        brcmf_err("bcn_timeout error (%d)\n", err);
4348                        goto dongle_rom_out;
4349                }
4350        }
4351
4352        /*
4353         * Enable/Disable built-in roaming to allow supplicant
4354         * to take care of roaming
4355         */
4356        brcmf_dbg(INFO, "Internal Roaming = %s\n", roamvar ? "Off" : "On");
4357        err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
4358        if (err) {
4359                brcmf_err("roam_off error (%d)\n", err);
4360                goto dongle_rom_out;
4361        }
4362
4363        roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
4364        roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
4365        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
4366                                     (void *)roamtrigger, sizeof(roamtrigger));
4367        if (err) {
4368                brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
4369                goto dongle_rom_out;
4370        }
4371
4372        roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
4373        roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
4374        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
4375                                     (void *)roam_delta, sizeof(roam_delta));
4376        if (err) {
4377                brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
4378                goto dongle_rom_out;
4379        }
4380
4381dongle_rom_out:
4382        return err;
4383}
4384
4385static s32
4386brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
4387                      s32 scan_unassoc_time, s32 scan_passive_time)
4388{
4389        struct brcmf_if *ifp = netdev_priv(ndev);
4390        s32 err = 0;
4391
4392        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
4393                                    scan_assoc_time);
4394        if (err) {
4395                if (err == -EOPNOTSUPP)
4396                        brcmf_dbg(INFO, "Scan assoc time is not supported\n");
4397                else
4398                        brcmf_err("Scan assoc time error (%d)\n", err);
4399                goto dongle_scantime_out;
4400        }
4401        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
4402                                    scan_unassoc_time);
4403        if (err) {
4404                if (err == -EOPNOTSUPP)
4405                        brcmf_dbg(INFO, "Scan unassoc time is not supported\n");
4406                else
4407                        brcmf_err("Scan unassoc time error (%d)\n", err);
4408                goto dongle_scantime_out;
4409        }
4410
4411        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
4412                                    scan_passive_time);
4413        if (err) {
4414                if (err == -EOPNOTSUPP)
4415                        brcmf_dbg(INFO, "Scan passive time is not supported\n");
4416                else
4417                        brcmf_err("Scan passive time error (%d)\n", err);
4418                goto dongle_scantime_out;
4419        }
4420
4421dongle_scantime_out:
4422        return err;
4423}
4424
4425static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg)
4426{
4427        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
4428        struct wiphy *wiphy;
4429        s32 phy_list;
4430        s8 phy;
4431        s32 err = 0;
4432
4433        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
4434                                     &phy_list, sizeof(phy_list));
4435        if (err) {
4436                brcmf_err("error (%d)\n", err);
4437                return err;
4438        }
4439
4440        phy = ((char *)&phy_list)[0];
4441        brcmf_dbg(INFO, "%c phy\n", phy);
4442        if (phy == 'n' || phy == 'a') {
4443                wiphy = cfg_to_wiphy(cfg);
4444                wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
4445        }
4446
4447        return err;
4448}
4449
4450static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
4451{
4452        return wl_update_wiphybands(cfg);
4453}
4454
4455static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
4456{
4457        struct net_device *ndev;
4458        struct wireless_dev *wdev;
4459        s32 power_mode;
4460        s32 err = 0;
4461
4462        if (cfg->dongle_up)
4463                return err;
4464
4465        ndev = cfg_to_ndev(cfg);
4466        wdev = ndev->ieee80211_ptr;
4467
4468        brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
4469                        WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
4470
4471        power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
4472        err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM,
4473                                    power_mode);
4474        if (err)
4475                goto default_conf_out;
4476        brcmf_dbg(INFO, "power save set to %s\n",
4477                  (power_mode ? "enabled" : "disabled"));
4478
4479        err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1),
4480                                WL_BEACON_TIMEOUT);
4481        if (err)
4482                goto default_conf_out;
4483        err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
4484                                          NULL, NULL);
4485        if (err && err != -EINPROGRESS)
4486                goto default_conf_out;
4487        err = brcmf_dongle_probecap(cfg);
4488        if (err)
4489                goto default_conf_out;
4490
4491        /* -EINPROGRESS: Call commit handler */
4492
4493default_conf_out:
4494
4495        cfg->dongle_up = true;
4496
4497        return err;
4498
4499}
4500
4501static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
4502{
4503        set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
4504        if (ifp->idx)
4505                return 0;
4506
4507        return brcmf_config_dongle(ifp->drvr->config);
4508}
4509
4510static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
4511{
4512        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4513
4514        /*
4515         * While going down, if associated with AP disassociate
4516         * from AP to save power
4517         */
4518        if (check_vif_up(ifp->vif)) {
4519                brcmf_link_down(ifp->vif);
4520
4521                /* Make sure WPA_Supplicant receives all the event
4522                   generated due to DISASSOC call to the fw to keep
4523                   the state fw and WPA_Supplicant state consistent
4524                 */
4525                brcmf_delay(500);
4526        }
4527
4528        brcmf_abort_scanning(cfg);
4529        clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
4530
4531        return 0;
4532}
4533
4534s32 brcmf_cfg80211_up(struct net_device *ndev)
4535{
4536        struct brcmf_if *ifp = netdev_priv(ndev);
4537        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4538        s32 err = 0;
4539
4540        mutex_lock(&cfg->usr_sync);
4541        err = __brcmf_cfg80211_up(ifp);
4542        mutex_unlock(&cfg->usr_sync);
4543
4544        return err;
4545}
4546
4547s32 brcmf_cfg80211_down(struct net_device *ndev)
4548{
4549        struct brcmf_if *ifp = netdev_priv(ndev);
4550        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4551        s32 err = 0;
4552
4553        mutex_lock(&cfg->usr_sync);
4554        err = __brcmf_cfg80211_down(ifp);
4555        mutex_unlock(&cfg->usr_sync);
4556
4557        return err;
4558}
4559
4560