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