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, void *data, int len)
3159{
3160        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3161        struct net_device *ndev = cfg_to_ndev(cfg);
3162        struct brcmf_dcmd *dcmd = data;
3163        struct sk_buff *reply;
3164        int ret;
3165
3166        brcmf_dbg(TRACE, "cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
3167                  dcmd->buf, dcmd->len);
3168
3169        if (dcmd->set)
3170                ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
3171                                             dcmd->buf, dcmd->len);
3172        else
3173                ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
3174                                             dcmd->buf, dcmd->len);
3175        if (ret == 0) {
3176                reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3177                nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3178                ret = cfg80211_testmode_reply(reply);
3179        }
3180        return ret;
3181}
3182#endif
3183
3184static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
3185{
3186        s32 err;
3187
3188        /* set auth */
3189        err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
3190        if (err < 0) {
3191                brcmf_err("auth error %d\n", err);
3192                return err;
3193        }
3194        /* set wsec */
3195        err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
3196        if (err < 0) {
3197                brcmf_err("wsec error %d\n", err);
3198                return err;
3199        }
3200        /* set upper-layer auth */
3201        err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE);
3202        if (err < 0) {
3203                brcmf_err("wpa_auth error %d\n", err);
3204                return err;
3205        }
3206
3207        return 0;
3208}
3209
3210static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
3211{
3212        if (is_rsn_ie)
3213                return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
3214
3215        return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
3216}
3217
3218static s32
3219brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
3220                     bool is_rsn_ie)
3221{
3222        struct brcmf_if *ifp = netdev_priv(ndev);
3223        u32 auth = 0; /* d11 open authentication */
3224        u16 count;
3225        s32 err = 0;
3226        s32 len = 0;
3227        u32 i;
3228        u32 wsec;
3229        u32 pval = 0;
3230        u32 gval = 0;
3231        u32 wpa_auth = 0;
3232        u32 offset;
3233        u8 *data;
3234        u16 rsn_cap;
3235        u32 wme_bss_disable;
3236
3237        brcmf_dbg(TRACE, "Enter\n");
3238        if (wpa_ie == NULL)
3239                goto exit;
3240
3241        len = wpa_ie->len + TLV_HDR_LEN;
3242        data = (u8 *)wpa_ie;
3243        offset = TLV_HDR_LEN;
3244        if (!is_rsn_ie)
3245                offset += VS_IE_FIXED_HDR_LEN;
3246        else
3247                offset += WPA_IE_VERSION_LEN;
3248
3249        /* check for multicast cipher suite */
3250        if (offset + WPA_IE_MIN_OUI_LEN > len) {
3251                err = -EINVAL;
3252                brcmf_err("no multicast cipher suite\n");
3253                goto exit;
3254        }
3255
3256        if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3257                err = -EINVAL;
3258                brcmf_err("ivalid OUI\n");
3259                goto exit;
3260        }
3261        offset += TLV_OUI_LEN;
3262
3263        /* pick up multicast cipher */
3264        switch (data[offset]) {
3265        case WPA_CIPHER_NONE:
3266                gval = 0;
3267                break;
3268        case WPA_CIPHER_WEP_40:
3269        case WPA_CIPHER_WEP_104:
3270                gval = WEP_ENABLED;
3271                break;
3272        case WPA_CIPHER_TKIP:
3273                gval = TKIP_ENABLED;
3274                break;
3275        case WPA_CIPHER_AES_CCM:
3276                gval = AES_ENABLED;
3277                break;
3278        default:
3279                err = -EINVAL;
3280                brcmf_err("Invalid multi cast cipher info\n");
3281                goto exit;
3282        }
3283
3284        offset++;
3285        /* walk thru unicast cipher list and pick up what we recognize */
3286        count = data[offset] + (data[offset + 1] << 8);
3287        offset += WPA_IE_SUITE_COUNT_LEN;
3288        /* Check for unicast suite(s) */
3289        if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3290                err = -EINVAL;
3291                brcmf_err("no unicast cipher suite\n");
3292                goto exit;
3293        }
3294        for (i = 0; i < count; i++) {
3295                if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3296                        err = -EINVAL;
3297                        brcmf_err("ivalid OUI\n");
3298                        goto exit;
3299                }
3300                offset += TLV_OUI_LEN;
3301                switch (data[offset]) {
3302                case WPA_CIPHER_NONE:
3303                        break;
3304                case WPA_CIPHER_WEP_40:
3305                case WPA_CIPHER_WEP_104:
3306                        pval |= WEP_ENABLED;
3307                        break;
3308                case WPA_CIPHER_TKIP:
3309                        pval |= TKIP_ENABLED;
3310                        break;
3311                case WPA_CIPHER_AES_CCM:
3312                        pval |= AES_ENABLED;
3313                        break;
3314                default:
3315                        brcmf_err("Ivalid unicast security info\n");
3316                }
3317                offset++;
3318        }
3319        /* walk thru auth management suite list and pick up what we recognize */
3320        count = data[offset] + (data[offset + 1] << 8);
3321        offset += WPA_IE_SUITE_COUNT_LEN;
3322        /* Check for auth key management suite(s) */
3323        if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3324                err = -EINVAL;
3325                brcmf_err("no auth key mgmt suite\n");
3326                goto exit;
3327        }
3328        for (i = 0; i < count; i++) {
3329                if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3330                        err = -EINVAL;
3331                        brcmf_err("ivalid OUI\n");
3332                        goto exit;
3333                }
3334                offset += TLV_OUI_LEN;
3335                switch (data[offset]) {
3336                case RSN_AKM_NONE:
3337                        brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
3338                        wpa_auth |= WPA_AUTH_NONE;
3339                        break;
3340                case RSN_AKM_UNSPECIFIED:
3341                        brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
3342                        is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
3343                                    (wpa_auth |= WPA_AUTH_UNSPECIFIED);
3344                        break;
3345                case RSN_AKM_PSK:
3346                        brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
3347                        is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
3348                                    (wpa_auth |= WPA_AUTH_PSK);
3349                        break;
3350                default:
3351                        brcmf_err("Ivalid key mgmt info\n");
3352                }
3353                offset++;
3354        }
3355
3356        if (is_rsn_ie) {
3357                wme_bss_disable = 1;
3358                if ((offset + RSN_CAP_LEN) <= len) {
3359                        rsn_cap = data[offset] + (data[offset + 1] << 8);
3360                        if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
3361                                wme_bss_disable = 0;
3362                }
3363                /* set wme_bss_disable to sync RSN Capabilities */
3364                err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
3365                                               wme_bss_disable);
3366                if (err < 0) {
3367                        brcmf_err("wme_bss_disable error %d\n", err);
3368                        goto exit;
3369                }
3370        }
3371        /* FOR WPS , set SES_OW_ENABLED */
3372        wsec = (pval | gval | SES_OW_ENABLED);
3373
3374        /* set auth */
3375        err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
3376        if (err < 0) {
3377                brcmf_err("auth error %d\n", err);
3378                goto exit;
3379        }
3380        /* set wsec */
3381        err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
3382        if (err < 0) {
3383                brcmf_err("wsec error %d\n", err);
3384                goto exit;
3385        }
3386        /* set upper-layer auth */
3387        err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
3388        if (err < 0) {
3389                brcmf_err("wpa_auth error %d\n", err);
3390                goto exit;
3391        }
3392
3393exit:
3394        return err;
3395}
3396
3397static s32
3398brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
3399                     struct parsed_vndr_ies *vndr_ies)
3400{
3401        s32 err = 0;
3402        struct brcmf_vs_tlv *vndrie;
3403        struct brcmf_tlv *ie;
3404        struct parsed_vndr_ie_info *parsed_info;
3405        s32 remaining_len;
3406
3407        remaining_len = (s32)vndr_ie_len;
3408        memset(vndr_ies, 0, sizeof(*vndr_ies));
3409
3410        ie = (struct brcmf_tlv *)vndr_ie_buf;
3411        while (ie) {
3412                if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
3413                        goto next;
3414                vndrie = (struct brcmf_vs_tlv *)ie;
3415                /* len should be bigger than OUI length + one */
3416                if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
3417                        brcmf_err("invalid vndr ie. length is too small %d\n",
3418                                  vndrie->len);
3419                        goto next;
3420                }
3421                /* if wpa or wme ie, do not add ie */
3422                if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
3423                    ((vndrie->oui_type == WPA_OUI_TYPE) ||
3424                    (vndrie->oui_type == WME_OUI_TYPE))) {
3425                        brcmf_dbg(TRACE, "Found WPA/WME oui. Do not add it\n");
3426                        goto next;
3427                }
3428
3429                parsed_info = &vndr_ies->ie_info[vndr_ies->count];
3430
3431                /* save vndr ie information */
3432                parsed_info->ie_ptr = (char *)vndrie;
3433                parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
3434                memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
3435
3436                vndr_ies->count++;
3437
3438                brcmf_dbg(TRACE, "** OUI %02x %02x %02x, type 0x%02x\n",
3439                          parsed_info->vndrie.oui[0],
3440                          parsed_info->vndrie.oui[1],
3441                          parsed_info->vndrie.oui[2],
3442                          parsed_info->vndrie.oui_type);
3443
3444                if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT)
3445                        break;
3446next:
3447                remaining_len -= (ie->len + TLV_HDR_LEN);
3448                if (remaining_len <= TLV_HDR_LEN)
3449                        ie = NULL;
3450                else
3451                        ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
3452                                TLV_HDR_LEN);
3453        }
3454        return err;
3455}
3456
3457static u32
3458brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
3459{
3460
3461        __le32 iecount_le;
3462        __le32 pktflag_le;
3463
3464        strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
3465        iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
3466
3467        iecount_le = cpu_to_le32(1);
3468        memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le));
3469
3470        pktflag_le = cpu_to_le32(pktflag);
3471        memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le));
3472
3473        memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
3474
3475        return ie_len + VNDR_IE_HDR_SIZE;
3476}
3477
3478s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
3479                          const u8 *vndr_ie_buf, u32 vndr_ie_len)
3480{
3481        struct brcmf_if *ifp;
3482        struct vif_saved_ie *saved_ie;
3483        s32 err = 0;
3484        u8  *iovar_ie_buf;
3485        u8  *curr_ie_buf;
3486        u8  *mgmt_ie_buf = NULL;
3487        int mgmt_ie_buf_len;
3488        u32 *mgmt_ie_len;
3489        u32 del_add_ie_buf_len = 0;
3490        u32 total_ie_buf_len = 0;
3491        u32 parsed_ie_buf_len = 0;
3492        struct parsed_vndr_ies old_vndr_ies;
3493        struct parsed_vndr_ies new_vndr_ies;
3494        struct parsed_vndr_ie_info *vndrie_info;
3495        s32 i;
3496        u8 *ptr;
3497        int remained_buf_len;
3498
3499        if (!vif)
3500                return -ENODEV;
3501        ifp = vif->ifp;
3502        saved_ie = &vif->saved_ie;
3503
3504        brcmf_dbg(TRACE, "bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag);
3505        iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3506        if (!iovar_ie_buf)
3507                return -ENOMEM;
3508        curr_ie_buf = iovar_ie_buf;
3509        switch (pktflag) {
3510        case BRCMF_VNDR_IE_PRBREQ_FLAG:
3511                mgmt_ie_buf = saved_ie->probe_req_ie;
3512                mgmt_ie_len = &saved_ie->probe_req_ie_len;
3513                mgmt_ie_buf_len = sizeof(saved_ie->probe_req_ie);
3514                break;
3515        case BRCMF_VNDR_IE_PRBRSP_FLAG:
3516                mgmt_ie_buf = saved_ie->probe_res_ie;
3517                mgmt_ie_len = &saved_ie->probe_res_ie_len;
3518                mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
3519                break;
3520        case BRCMF_VNDR_IE_BEACON_FLAG:
3521                mgmt_ie_buf = saved_ie->beacon_ie;
3522                mgmt_ie_len = &saved_ie->beacon_ie_len;
3523                mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);
3524                break;
3525        case BRCMF_VNDR_IE_ASSOCREQ_FLAG:
3526                mgmt_ie_buf = saved_ie->assoc_req_ie;
3527                mgmt_ie_len = &saved_ie->assoc_req_ie_len;
3528                mgmt_ie_buf_len = sizeof(saved_ie->assoc_req_ie);
3529                break;
3530        default:
3531                err = -EPERM;
3532                brcmf_err("not suitable type\n");
3533                goto exit;
3534        }
3535
3536        if (vndr_ie_len > mgmt_ie_buf_len) {
3537                err = -ENOMEM;
3538                brcmf_err("extra IE size too big\n");
3539                goto exit;
3540        }
3541
3542        /* parse and save new vndr_ie in curr_ie_buff before comparing it */
3543        if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {
3544                ptr = curr_ie_buf;
3545                brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);
3546                for (i = 0; i < new_vndr_ies.count; i++) {
3547                        vndrie_info = &new_vndr_ies.ie_info[i];
3548                        memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
3549                               vndrie_info->ie_len);
3550                        parsed_ie_buf_len += vndrie_info->ie_len;
3551                }
3552        }
3553
3554        if (mgmt_ie_buf && *mgmt_ie_len) {
3555                if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
3556                    (memcmp(mgmt_ie_buf, curr_ie_buf,
3557                            parsed_ie_buf_len) == 0)) {
3558                        brcmf_dbg(TRACE, "Previous mgmt IE equals to current IE\n");
3559                        goto exit;
3560                }
3561
3562                /* parse old vndr_ie */
3563                brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);
3564
3565                /* make a command to delete old ie */
3566                for (i = 0; i < old_vndr_ies.count; i++) {
3567                        vndrie_info = &old_vndr_ies.ie_info[i];
3568
3569                        brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
3570                                  vndrie_info->vndrie.id,
3571                                  vndrie_info->vndrie.len,
3572                                  vndrie_info->vndrie.oui[0],
3573                                  vndrie_info->vndrie.oui[1],
3574                                  vndrie_info->vndrie.oui[2]);
3575
3576                        del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3577                                                           vndrie_info->ie_ptr,
3578                                                           vndrie_info->ie_len,
3579                                                           "del");
3580                        curr_ie_buf += del_add_ie_buf_len;
3581                        total_ie_buf_len += del_add_ie_buf_len;
3582                }
3583        }
3584
3585        *mgmt_ie_len = 0;
3586        /* Add if there is any extra IE */
3587        if (mgmt_ie_buf && parsed_ie_buf_len) {
3588                ptr = mgmt_ie_buf;
3589
3590                remained_buf_len = mgmt_ie_buf_len;
3591
3592                /* make a command to add new ie */
3593                for (i = 0; i < new_vndr_ies.count; i++) {
3594                        vndrie_info = &new_vndr_ies.ie_info[i];
3595
3596                        /* verify remained buf size before copy data */
3597                        if (remained_buf_len < (vndrie_info->vndrie.len +
3598                                                        VNDR_IE_VSIE_OFFSET)) {
3599                                brcmf_err("no space in mgmt_ie_buf: len left %d",
3600                                          remained_buf_len);
3601                                break;
3602                        }
3603                        remained_buf_len -= (vndrie_info->ie_len +
3604                                             VNDR_IE_VSIE_OFFSET);
3605
3606                        brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
3607                                  vndrie_info->vndrie.id,
3608                                  vndrie_info->vndrie.len,
3609                                  vndrie_info->vndrie.oui[0],
3610                                  vndrie_info->vndrie.oui[1],
3611                                  vndrie_info->vndrie.oui[2]);
3612
3613                        del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3614                                                           vndrie_info->ie_ptr,
3615                                                           vndrie_info->ie_len,
3616                                                           "add");
3617
3618                        /* save the parsed IE in wl struct */
3619                        memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
3620                               vndrie_info->ie_len);
3621                        *mgmt_ie_len += vndrie_info->ie_len;
3622
3623                        curr_ie_buf += del_add_ie_buf_len;
3624                        total_ie_buf_len += del_add_ie_buf_len;
3625                }
3626        }
3627        if (total_ie_buf_len) {
3628                err  = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
3629                                                 total_ie_buf_len);
3630                if (err)
3631                        brcmf_err("vndr ie set error : %d\n", err);
3632        }
3633
3634exit:
3635        kfree(iovar_ie_buf);
3636        return err;
3637}
3638
3639s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)
3640{
3641        s32 pktflags[] = {
3642                BRCMF_VNDR_IE_PRBREQ_FLAG,
3643                BRCMF_VNDR_IE_PRBRSP_FLAG,
3644                BRCMF_VNDR_IE_BEACON_FLAG
3645        };
3646        int i;
3647
3648        for (i = 0; i < ARRAY_SIZE(pktflags); i++)
3649                brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);
3650
3651        memset(&vif->saved_ie, 0, sizeof(vif->saved_ie));
3652        return 0;
3653}
3654
3655static s32
3656brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
3657                        struct cfg80211_beacon_data *beacon)
3658{
3659        s32 err;
3660
3661        /* Set Beacon IEs to FW */
3662        err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG,
3663                                    beacon->tail, beacon->tail_len);
3664        if (err) {
3665                brcmf_err("Set Beacon IE Failed\n");
3666                return err;
3667        }
3668        brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");
3669
3670        /* Set Probe Response IEs to FW */
3671        err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBRSP_FLAG,
3672                                    beacon->proberesp_ies,
3673                                    beacon->proberesp_ies_len);
3674        if (err)
3675                brcmf_err("Set Probe Resp IE Failed\n");
3676        else
3677                brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");
3678
3679        return err;
3680}
3681
3682static s32
3683brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
3684                           struct brcmf_if *ifp,
3685                           struct ieee80211_channel *channel)
3686{
3687        u16 chanspec;
3688        s32 err;
3689
3690        brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
3691                  channel->center_freq);
3692
3693        chanspec = channel_to_chanspec(&cfg->d11inf, channel);
3694        err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
3695
3696        return err;
3697}
3698
3699static s32
3700brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
3701                        struct cfg80211_ap_settings *settings)
3702{
3703        s32 ie_offset;
3704        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3705        struct brcmf_if *ifp = netdev_priv(ndev);
3706        struct brcmf_tlv *ssid_ie;
3707        struct brcmf_ssid_le ssid_le;
3708        s32 err = -EPERM;
3709        struct brcmf_tlv *rsn_ie;
3710        struct brcmf_vs_tlv *wpa_ie;
3711        struct brcmf_join_params join_params;
3712        enum nl80211_iftype dev_role;
3713        struct brcmf_fil_bss_enable_le bss_enable;
3714
3715        brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
3716                  cfg80211_get_chandef_type(&settings->chandef),
3717                  settings->beacon_interval,
3718                  settings->dtim_period);
3719        brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
3720                  settings->ssid, settings->ssid_len, settings->auth_type,
3721                  settings->inactivity_timeout);
3722
3723        dev_role = ifp->vif->wdev.iftype;
3724
3725        memset(&ssid_le, 0, sizeof(ssid_le));
3726        if (settings->ssid == NULL || settings->ssid_len == 0) {
3727                ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
3728                ssid_ie = brcmf_parse_tlvs(
3729                                (u8 *)&settings->beacon.head[ie_offset],
3730                                settings->beacon.head_len - ie_offset,
3731                                WLAN_EID_SSID);
3732                if (!ssid_ie)
3733                        return -EINVAL;
3734
3735                memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
3736                ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
3737                brcmf_dbg(TRACE, "SSID is (%s) in Head\n", ssid_le.SSID);
3738        } else {
3739                memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
3740                ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
3741        }
3742
3743        brcmf_set_mpc(ifp, 0);
3744        brcmf_configure_arp_offload(ifp, false);
3745
3746        /* find the RSN_IE */
3747        rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
3748                                  settings->beacon.tail_len, WLAN_EID_RSN);
3749
3750        /* find the WPA_IE */
3751        wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
3752                                  settings->beacon.tail_len);
3753
3754        if ((wpa_ie != NULL || rsn_ie != NULL)) {
3755                brcmf_dbg(TRACE, "WPA(2) IE is found\n");
3756                if (wpa_ie != NULL) {
3757                        /* WPA IE */
3758                        err = brcmf_configure_wpaie(ndev, wpa_ie, false);
3759                        if (err < 0)
3760                                goto exit;
3761                } else {
3762                        /* RSN IE */
3763                        err = brcmf_configure_wpaie(ndev,
3764                                (struct brcmf_vs_tlv *)rsn_ie, true);
3765                        if (err < 0)
3766                                goto exit;
3767                }
3768        } else {
3769                brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
3770                brcmf_configure_opensecurity(ifp);
3771        }
3772
3773        brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
3774
3775        err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
3776        if (err < 0) {
3777                brcmf_err("Set Channel failed, %d\n", err);
3778                goto exit;
3779        }
3780
3781        if (settings->beacon_interval) {
3782                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
3783                                            settings->beacon_interval);
3784                if (err < 0) {
3785                        brcmf_err("Beacon Interval Set Error, %d\n", err);
3786                        goto exit;
3787                }
3788        }
3789        if (settings->dtim_period) {
3790                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
3791                                            settings->dtim_period);
3792                if (err < 0) {
3793                        brcmf_err("DTIM Interval Set Error, %d\n", err);
3794                        goto exit;
3795                }
3796        }
3797
3798        if (dev_role == NL80211_IFTYPE_AP) {
3799                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
3800                if (err < 0) {
3801                        brcmf_err("BRCMF_C_DOWN error %d\n", err);
3802                        goto exit;
3803                }
3804                brcmf_fil_iovar_int_set(ifp, "apsta", 0);
3805        }
3806
3807        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
3808        if (err < 0) {
3809                brcmf_err("SET INFRA error %d\n", err);
3810                goto exit;
3811        }
3812        if (dev_role == NL80211_IFTYPE_AP) {
3813                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
3814                if (err < 0) {
3815                        brcmf_err("setting AP mode failed %d\n", err);
3816                        goto exit;
3817                }
3818                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
3819                if (err < 0) {
3820                        brcmf_err("BRCMF_C_UP error (%d)\n", err);
3821                        goto exit;
3822                }
3823
3824                memset(&join_params, 0, sizeof(join_params));
3825                /* join parameters starts with ssid */
3826                memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
3827                /* create softap */
3828                err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
3829                                             &join_params, sizeof(join_params));
3830                if (err < 0) {
3831                        brcmf_err("SET SSID error (%d)\n", err);
3832                        goto exit;
3833                }
3834                brcmf_dbg(TRACE, "AP mode configuration complete\n");
3835        } else {
3836                err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
3837                                                sizeof(ssid_le));
3838                if (err < 0) {
3839                        brcmf_err("setting ssid failed %d\n", err);
3840                        goto exit;
3841                }
3842                bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
3843                bss_enable.enable = cpu_to_le32(1);
3844                err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
3845                                               sizeof(bss_enable));
3846                if (err < 0) {
3847                        brcmf_err("bss_enable config failed %d\n", err);
3848                        goto exit;
3849                }
3850
3851                brcmf_dbg(TRACE, "GO mode configuration complete\n");
3852        }
3853        clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
3854        set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
3855
3856exit:
3857        if (err) {
3858                brcmf_set_mpc(ifp, 1);
3859                brcmf_configure_arp_offload(ifp, true);
3860        }
3861        return err;
3862}
3863
3864static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
3865{
3866        struct brcmf_if *ifp = netdev_priv(ndev);
3867        s32 err;
3868        struct brcmf_fil_bss_enable_le bss_enable;
3869        struct brcmf_join_params join_params;
3870
3871        brcmf_dbg(TRACE, "Enter\n");
3872
3873        if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) {
3874                /* Due to most likely deauths outstanding we sleep */
3875                /* first to make sure they get processed by fw. */
3876                msleep(400);
3877
3878                memset(&join_params, 0, sizeof(join_params));
3879                err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
3880                                             &join_params, sizeof(join_params));
3881                if (err < 0)
3882                        brcmf_err("SET SSID error (%d)\n", err);
3883                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
3884                if (err < 0)
3885                        brcmf_err("BRCMF_C_UP error %d\n", err);
3886                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
3887                if (err < 0)
3888                        brcmf_err("setting AP mode failed %d\n", err);
3889                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
3890                if (err < 0)
3891                        brcmf_err("setting INFRA mode failed %d\n", err);
3892        } else {
3893                bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
3894                bss_enable.enable = cpu_to_le32(0);
3895                err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
3896                                               sizeof(bss_enable));
3897                if (err < 0)
3898                        brcmf_err("bss_enable config failed %d\n", err);
3899        }
3900        brcmf_set_mpc(ifp, 1);
3901        brcmf_configure_arp_offload(ifp, true);
3902        set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
3903        clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
3904
3905        return err;
3906}
3907
3908static s32
3909brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
3910                             struct cfg80211_beacon_data *info)
3911{
3912        struct brcmf_if *ifp = netdev_priv(ndev);
3913        s32 err;
3914
3915        brcmf_dbg(TRACE, "Enter\n");
3916
3917        err = brcmf_config_ap_mgmt_ie(ifp->vif, info);
3918
3919        return err;
3920}
3921
3922static int
3923brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
3924                           u8 *mac)
3925{
3926        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3927        struct brcmf_scb_val_le scbval;
3928        struct brcmf_if *ifp = netdev_priv(ndev);
3929        s32 err;
3930
3931        if (!mac)
3932                return -EFAULT;
3933
3934        brcmf_dbg(TRACE, "Enter %pM\n", mac);
3935
3936        if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
3937                ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
3938        if (!check_vif_up(ifp->vif))
3939                return -EIO;
3940
3941        memcpy(&scbval.ea, mac, ETH_ALEN);
3942        scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
3943        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
3944                                     &scbval, sizeof(scbval));
3945        if (err)
3946                brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
3947
3948        brcmf_dbg(TRACE, "Exit\n");
3949        return err;
3950}
3951
3952
3953static void
3954brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
3955                                   struct wireless_dev *wdev,
3956                                   u16 frame_type, bool reg)
3957{
3958        struct brcmf_cfg80211_vif *vif;
3959        u16 mgmt_type;
3960
3961        brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
3962
3963        mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
3964        vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
3965        if (reg)
3966                vif->mgmt_rx_reg |= BIT(mgmt_type);
3967        else
3968                vif->mgmt_rx_reg &= ~BIT(mgmt_type);
3969}
3970
3971
3972static int
3973brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3974                       struct ieee80211_channel *chan, bool offchan,
3975                       unsigned int wait, const u8 *buf, size_t len,
3976                       bool no_cck, bool dont_wait_for_ack, u64 *cookie)
3977{
3978        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3979        const struct ieee80211_mgmt *mgmt;
3980        struct brcmf_cfg80211_vif *vif;
3981        s32 err = 0;
3982        s32 ie_offset;
3983        s32 ie_len;
3984        struct brcmf_fil_action_frame_le *action_frame;
3985        struct brcmf_fil_af_params_le *af_params;
3986        bool ack;
3987        s32 chan_nr;
3988        u32 freq;
3989
3990        brcmf_dbg(TRACE, "Enter\n");
3991
3992        *cookie = 0;
3993
3994        mgmt = (const struct ieee80211_mgmt *)buf;
3995
3996        if (!ieee80211_is_mgmt(mgmt->frame_control)) {
3997                brcmf_err("Driver only allows MGMT packet type\n");
3998                return -EPERM;
3999        }
4000
4001        vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
4002
4003        if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4004                /* Right now the only reason to get a probe response */
4005                /* is for p2p listen response or for p2p GO from     */
4006                /* wpa_supplicant. Unfortunately the probe is send   */
4007                /* on primary ndev, while dongle wants it on the p2p */
4008                /* vif. Since this is only reason for a probe        */
4009                /* response to be sent, the vif is taken from cfg.   */
4010                /* If ever desired to send proberesp for non p2p     */
4011                /* response then data should be checked for          */
4012                /* "DIRECT-". Note in future supplicant will take    */
4013                /* dedicated p2p wdev to do this and then this 'hack'*/
4014                /* is not needed anymore.                            */
4015                ie_offset =  DOT11_MGMT_HDR_LEN +
4016                             DOT11_BCN_PRB_FIXED_LEN;
4017                ie_len = len - ie_offset;
4018                if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)
4019                        vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
4020                err = brcmf_vif_set_mgmt_ie(vif,
4021                                            BRCMF_VNDR_IE_PRBRSP_FLAG,
4022                                            &buf[ie_offset],
4023                                            ie_len);
4024                cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
4025                                        GFP_KERNEL);
4026        } else if (ieee80211_is_action(mgmt->frame_control)) {
4027                af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
4028                if (af_params == NULL) {
4029                        brcmf_err("unable to allocate frame\n");
4030                        err = -ENOMEM;
4031                        goto exit;
4032                }
4033                action_frame = &af_params->action_frame;
4034                /* Add the packet Id */
4035                action_frame->packet_id = cpu_to_le32(*cookie);
4036                /* Add BSSID */
4037                memcpy(&action_frame->da[0], &mgmt->da[0], ETH_ALEN);
4038                memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
4039                /* Add the length exepted for 802.11 header  */
4040                action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
4041                /* Add the channel. Use the one specified as parameter if any or
4042                 * the current one (got from the firmware) otherwise
4043                 */
4044                if (chan)
4045                        freq = chan->center_freq;
4046                else
4047                        brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL,
4048                                              &freq);
4049                chan_nr = ieee80211_frequency_to_channel(freq);
4050                af_params->channel = cpu_to_le32(chan_nr);
4051
4052                memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN],
4053                       le16_to_cpu(action_frame->len));
4054
4055                brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n",
4056                          *cookie, le16_to_cpu(action_frame->len), freq);
4057
4058                ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg),
4059                                                  af_params);
4060
4061                cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
4062                                        GFP_KERNEL);
4063                kfree(af_params);
4064        } else {
4065                brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
4066                brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len);
4067        }
4068
4069exit:
4070        return err;
4071}
4072
4073
4074static int
4075brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
4076                                        struct wireless_dev *wdev,
4077                                        u64 cookie)
4078{
4079        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
4080        struct brcmf_cfg80211_vif *vif;
4081        int err = 0;
4082
4083        brcmf_dbg(TRACE, "Enter p2p listen cancel\n");
4084
4085        vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
4086        if (vif == NULL) {
4087                brcmf_err("No p2p device available for probe response\n");
4088                err = -ENODEV;
4089                goto exit;
4090        }
4091        brcmf_p2p_cancel_remain_on_channel(vif->ifp);
4092exit:
4093        return err;
4094}
4095
4096static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
4097                                           struct wireless_dev *wdev,
4098                                           enum nl80211_crit_proto_id proto,
4099                                           u16 duration)
4100{
4101        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
4102        struct brcmf_cfg80211_vif *vif;
4103
4104        vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
4105
4106        /* only DHCP support for now */
4107        if (proto != NL80211_CRIT_PROTO_DHCP)
4108                return -EINVAL;
4109
4110        /* suppress and abort scanning */
4111        set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
4112        brcmf_abort_scanning(cfg);
4113
4114        return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);
4115}
4116
4117static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
4118                                           struct wireless_dev *wdev)
4119{
4120        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
4121        struct brcmf_cfg80211_vif *vif;
4122
4123        vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
4124
4125        brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
4126        clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
4127}
4128
4129static struct cfg80211_ops wl_cfg80211_ops = {
4130        .add_virtual_intf = brcmf_cfg80211_add_iface,
4131        .del_virtual_intf = brcmf_cfg80211_del_iface,
4132        .change_virtual_intf = brcmf_cfg80211_change_iface,
4133        .scan = brcmf_cfg80211_scan,
4134        .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
4135        .join_ibss = brcmf_cfg80211_join_ibss,
4136        .leave_ibss = brcmf_cfg80211_leave_ibss,
4137        .get_station = brcmf_cfg80211_get_station,
4138        .set_tx_power = brcmf_cfg80211_set_tx_power,
4139        .get_tx_power = brcmf_cfg80211_get_tx_power,
4140        .add_key = brcmf_cfg80211_add_key,
4141        .del_key = brcmf_cfg80211_del_key,
4142        .get_key = brcmf_cfg80211_get_key,
4143        .set_default_key = brcmf_cfg80211_config_default_key,
4144        .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
4145        .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
4146        .connect = brcmf_cfg80211_connect,
4147        .disconnect = brcmf_cfg80211_disconnect,
4148        .suspend = brcmf_cfg80211_suspend,
4149        .resume = brcmf_cfg80211_resume,
4150        .set_pmksa = brcmf_cfg80211_set_pmksa,
4151        .del_pmksa = brcmf_cfg80211_del_pmksa,
4152        .flush_pmksa = brcmf_cfg80211_flush_pmksa,
4153        .start_ap = brcmf_cfg80211_start_ap,
4154        .stop_ap = brcmf_cfg80211_stop_ap,
4155        .change_beacon = brcmf_cfg80211_change_beacon,
4156        .del_station = brcmf_cfg80211_del_station,
4157        .sched_scan_start = brcmf_cfg80211_sched_scan_start,
4158        .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
4159        .mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
4160        .mgmt_tx = brcmf_cfg80211_mgmt_tx,
4161        .remain_on_channel = brcmf_p2p_remain_on_channel,
4162        .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
4163        .start_p2p_device = brcmf_p2p_start_device,
4164        .stop_p2p_device = brcmf_p2p_stop_device,
4165        .crit_proto_start = brcmf_cfg80211_crit_proto_start,
4166        .crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
4167#ifdef CONFIG_NL80211_TESTMODE
4168        .testmode_cmd = brcmf_cfg80211_testmode
4169#endif
4170};
4171
4172static s32 brcmf_nl80211_iftype_to_mode(enum nl80211_iftype type)
4173{
4174        switch (type) {
4175        case NL80211_IFTYPE_AP_VLAN:
4176        case NL80211_IFTYPE_WDS:
4177        case NL80211_IFTYPE_MONITOR:
4178        case NL80211_IFTYPE_MESH_POINT:
4179                return -ENOTSUPP;
4180        case NL80211_IFTYPE_ADHOC:
4181                return WL_MODE_IBSS;
4182        case NL80211_IFTYPE_STATION:
4183        case NL80211_IFTYPE_P2P_CLIENT:
4184                return WL_MODE_BSS;
4185        case NL80211_IFTYPE_AP:
4186        case NL80211_IFTYPE_P2P_GO:
4187                return WL_MODE_AP;
4188        case NL80211_IFTYPE_P2P_DEVICE:
4189                return WL_MODE_P2P;
4190        case NL80211_IFTYPE_UNSPECIFIED:
4191        default:
4192                break;
4193        }
4194
4195        return -EINVAL;
4196}
4197
4198static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
4199{
4200        /* scheduled scan settings */
4201        wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
4202        wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
4203        wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4204        wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4205}
4206
4207static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
4208        {
4209                .max = 2,
4210                .types = BIT(NL80211_IFTYPE_STATION) |
4211                         BIT(NL80211_IFTYPE_ADHOC) |
4212                         BIT(NL80211_IFTYPE_AP)
4213        },
4214        {
4215                .max = 1,
4216                .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
4217                         BIT(NL80211_IFTYPE_P2P_GO)
4218        },
4219        {
4220                .max = 1,
4221                .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
4222        }
4223};
4224static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
4225        {
4226                 .max_interfaces = BRCMF_IFACE_MAX_CNT,
4227                 .num_different_channels = 2,
4228                 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
4229                 .limits = brcmf_iface_limits
4230        }
4231};
4232
4233static const struct ieee80211_txrx_stypes
4234brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
4235        [NL80211_IFTYPE_STATION] = {
4236                .tx = 0xffff,
4237                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4238                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4239        },
4240        [NL80211_IFTYPE_P2P_CLIENT] = {
4241                .tx = 0xffff,
4242                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4243                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4244        },
4245        [NL80211_IFTYPE_P2P_GO] = {
4246                .tx = 0xffff,
4247                .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
4248                      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
4249                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
4250                      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
4251                      BIT(IEEE80211_STYPE_AUTH >> 4) |
4252                      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
4253                      BIT(IEEE80211_STYPE_ACTION >> 4)
4254        },
4255        [NL80211_IFTYPE_P2P_DEVICE] = {
4256                .tx = 0xffff,
4257                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4258                      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4259        }
4260};
4261
4262static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
4263{
4264        struct wiphy *wiphy;
4265        s32 err = 0;
4266
4267        wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
4268        if (!wiphy) {
4269                brcmf_err("Could not allocate wiphy device\n");
4270                return ERR_PTR(-ENOMEM);
4271        }
4272        set_wiphy_dev(wiphy, phydev);
4273        wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
4274        wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4275        wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
4276        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4277                                 BIT(NL80211_IFTYPE_ADHOC) |
4278                                 BIT(NL80211_IFTYPE_AP) |
4279                                 BIT(NL80211_IFTYPE_P2P_CLIENT) |
4280                                 BIT(NL80211_IFTYPE_P2P_GO) |
4281                                 BIT(NL80211_IFTYPE_P2P_DEVICE);
4282        wiphy->iface_combinations = brcmf_iface_combos;
4283        wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
4284        wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4285        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4286        wiphy->cipher_suites = __wl_cipher_suites;
4287        wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4288        wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
4289                        WIPHY_FLAG_OFFCHAN_TX |
4290                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
4291        wiphy->mgmt_stypes = brcmf_txrx_stypes;
4292        wiphy->max_remain_on_channel_duration = 5000;
4293        brcmf_wiphy_pno_params(wiphy);
4294        brcmf_dbg(INFO, "Registering custom regulatory\n");
4295        wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
4296        wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
4297        err = wiphy_register(wiphy);
4298        if (err < 0) {
4299                brcmf_err("Could not register wiphy device (%d)\n", err);
4300                wiphy_free(wiphy);
4301                return ERR_PTR(err);
4302        }
4303        return wiphy;
4304}
4305
4306struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
4307                                           enum nl80211_iftype type,
4308                                           bool pm_block)
4309{
4310        struct brcmf_cfg80211_vif *vif;
4311
4312        if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
4313                return ERR_PTR(-ENOSPC);
4314
4315        brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
4316                  sizeof(*vif));
4317        vif = kzalloc(sizeof(*vif), GFP_KERNEL);
4318        if (!vif)
4319                return ERR_PTR(-ENOMEM);
4320
4321        vif->wdev.wiphy = cfg->wiphy;
4322        vif->wdev.iftype = type;
4323
4324        vif->mode = brcmf_nl80211_iftype_to_mode(type);
4325        vif->pm_block = pm_block;
4326        vif->roam_off = -1;
4327
4328        brcmf_init_prof(&vif->profile);
4329
4330        list_add_tail(&vif->list, &cfg->vif_list);
4331        cfg->vif_cnt++;
4332        return vif;
4333}
4334
4335void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
4336                    struct brcmf_cfg80211_vif *vif)
4337{
4338        list_del(&vif->list);
4339        cfg->vif_cnt--;
4340
4341        kfree(vif);
4342        if (!cfg->vif_cnt) {
4343                wiphy_unregister(cfg->wiphy);
4344                wiphy_free(cfg->wiphy);
4345        }
4346}
4347
4348static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
4349{
4350        u32 event = e->event_code;
4351        u32 status = e->status;
4352
4353        if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
4354                brcmf_dbg(CONN, "Processing set ssid\n");
4355                return true;
4356        }
4357
4358        return false;
4359}
4360
4361static bool brcmf_is_linkdown(const struct brcmf_event_msg *e)
4362{
4363        u32 event = e->event_code;
4364        u16 flags = e->flags;
4365
4366        if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
4367                brcmf_dbg(CONN, "Processing link down\n");
4368                return true;
4369        }
4370        return false;
4371}
4372
4373static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
4374                               const struct brcmf_event_msg *e)
4375{
4376        u32 event = e->event_code;
4377        u32 status = e->status;
4378
4379        if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
4380                brcmf_dbg(CONN, "Processing Link %s & no network found\n",
4381                          e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");
4382                return true;
4383        }
4384
4385        if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
4386                brcmf_dbg(CONN, "Processing connecting & no network found\n");
4387                return true;
4388        }
4389
4390        return false;
4391}
4392
4393static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
4394{
4395        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4396
4397        kfree(conn_info->req_ie);
4398        conn_info->req_ie = NULL;
4399        conn_info->req_ie_len = 0;
4400        kfree(conn_info->resp_ie);
4401        conn_info->resp_ie = NULL;
4402        conn_info->resp_ie_len = 0;
4403}
4404
4405static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
4406                               struct brcmf_if *ifp)
4407{
4408        struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
4409        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4410        u32 req_len;
4411        u32 resp_len;
4412        s32 err = 0;
4413
4414        brcmf_clear_assoc_ies(cfg);
4415
4416        err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
4417                                       cfg->extra_buf, WL_ASSOC_INFO_MAX);
4418        if (err) {
4419                brcmf_err("could not get assoc info (%d)\n", err);
4420                return err;
4421        }
4422        assoc_info =
4423                (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
4424        req_len = le32_to_cpu(assoc_info->req_len);
4425        resp_len = le32_to_cpu(assoc_info->resp_len);
4426        if (req_len) {
4427                err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
4428                                               cfg->extra_buf,
4429                                               WL_ASSOC_INFO_MAX);
4430                if (err) {
4431                        brcmf_err("could not get assoc req (%d)\n", err);
4432                        return err;
4433                }
4434                conn_info->req_ie_len = req_len;
4435                conn_info->req_ie =
4436                    kmemdup(cfg->extra_buf, conn_info->req_ie_len,
4437                            GFP_KERNEL);
4438        } else {
4439                conn_info->req_ie_len = 0;
4440                conn_info->req_ie = NULL;
4441        }
4442        if (resp_len) {
4443                err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
4444                                               cfg->extra_buf,
4445                                               WL_ASSOC_INFO_MAX);
4446                if (err) {
4447                        brcmf_err("could not get assoc resp (%d)\n", err);
4448                        return err;
4449                }
4450                conn_info->resp_ie_len = resp_len;
4451                conn_info->resp_ie =
4452                    kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
4453                            GFP_KERNEL);
4454        } else {
4455                conn_info->resp_ie_len = 0;
4456                conn_info->resp_ie = NULL;
4457        }
4458        brcmf_dbg(CONN, "req len (%d) resp len (%d)\n",
4459                  conn_info->req_ie_len, conn_info->resp_ie_len);
4460
4461        return err;
4462}
4463
4464static s32
4465brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
4466                       struct net_device *ndev,
4467                       const struct brcmf_event_msg *e)
4468{
4469        struct brcmf_if *ifp = netdev_priv(ndev);
4470        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4471        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4472        struct wiphy *wiphy = cfg_to_wiphy(cfg);
4473        struct ieee80211_channel *notify_channel = NULL;
4474        struct ieee80211_supported_band *band;
4475        struct brcmf_bss_info_le *bi;
4476        struct brcmu_chan ch;
4477        u32 freq;
4478        s32 err = 0;
4479        u8 *buf;
4480
4481        brcmf_dbg(TRACE, "Enter\n");
4482
4483        brcmf_get_assoc_ies(cfg, ifp);
4484        memcpy(profile->bssid, e->addr, ETH_ALEN);
4485        brcmf_update_bss_info(cfg, ifp);
4486
4487        buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
4488        if (buf == NULL) {
4489                err = -ENOMEM;
4490                goto done;
4491        }
4492
4493        /* data sent to dongle has to be little endian */
4494        *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
4495        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
4496                                     buf, WL_BSS_INFO_MAX);
4497
4498        if (err)
4499                goto done;
4500
4501        bi = (struct brcmf_bss_info_le *)(buf + 4);
4502        ch.chspec = le16_to_cpu(bi->chanspec);
4503        cfg->d11inf.decchspec(&ch);
4504
4505        if (ch.band == BRCMU_CHAN_BAND_2G)
4506                band = wiphy->bands[IEEE80211_BAND_2GHZ];
4507        else
4508                band = wiphy->bands[IEEE80211_BAND_5GHZ];
4509
4510        freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
4511        notify_channel = ieee80211_get_channel(wiphy, freq);
4512
4513done:
4514        kfree(buf);
4515        cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
4516                        conn_info->req_ie, conn_info->req_ie_len,
4517                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
4518        brcmf_dbg(CONN, "Report roaming result\n");
4519
4520        set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
4521        brcmf_dbg(TRACE, "Exit\n");
4522        return err;
4523}
4524
4525static s32
4526brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
4527                       struct net_device *ndev, const struct brcmf_event_msg *e,
4528                       bool completed)
4529{
4530        struct brcmf_if *ifp = netdev_priv(ndev);
4531        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4532        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4533        s32 err = 0;
4534
4535        brcmf_dbg(TRACE, "Enter\n");
4536
4537        if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4538                               &ifp->vif->sme_state)) {
4539                if (completed) {
4540                        brcmf_get_assoc_ies(cfg, ifp);
4541                        memcpy(profile->bssid, e->addr, ETH_ALEN);
4542                        brcmf_update_bss_info(cfg, ifp);
4543                        set_bit(BRCMF_VIF_STATUS_CONNECTED,
4544                                &ifp->vif->sme_state);
4545                }
4546                cfg80211_connect_result(ndev,
4547                                        (u8 *)profile->bssid,
4548                                        conn_info->req_ie,
4549                                        conn_info->req_ie_len,
4550                                        conn_info->resp_ie,
4551                                        conn_info->resp_ie_len,
4552                                        completed ? WLAN_STATUS_SUCCESS :
4553                                                    WLAN_STATUS_AUTH_TIMEOUT,
4554                                        GFP_KERNEL);
4555                brcmf_dbg(CONN, "Report connect result - connection %s\n",
4556                          completed ? "succeeded" : "failed");
4557        }
4558        brcmf_dbg(TRACE, "Exit\n");
4559        return err;
4560}
4561
4562static s32
4563brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
4564                               struct net_device *ndev,
4565                               const struct brcmf_event_msg *e, void *data)
4566{
4567        static int generation;
4568        u32 event = e->event_code;
4569        u32 reason = e->reason;
4570        struct station_info sinfo;
4571
4572        brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
4573        if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
4574            ndev != cfg_to_ndev(cfg)) {
4575                brcmf_dbg(CONN, "AP mode link down\n");
4576                complete(&cfg->vif_disabled);
4577                return 0;
4578        }
4579
4580        if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
4581            (reason == BRCMF_E_STATUS_SUCCESS)) {
4582                memset(&sinfo, 0, sizeof(sinfo));
4583                sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
4584                if (!data) {
4585                        brcmf_err("No IEs present in ASSOC/REASSOC_IND");
4586                        return -EINVAL;
4587                }
4588                sinfo.assoc_req_ies = data;
4589                sinfo.assoc_req_ies_len = e->datalen;
4590                generation++;
4591                sinfo.generation = generation;
4592                cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_KERNEL);
4593        } else if ((event == BRCMF_E_DISASSOC_IND) ||
4594                   (event == BRCMF_E_DEAUTH_IND) ||
4595                   (event == BRCMF_E_DEAUTH)) {
4596                cfg80211_del_sta(ndev, e->addr, GFP_KERNEL);
4597        }
4598        return 0;
4599}
4600
4601static s32
4602brcmf_notify_connect_status(struct brcmf_if *ifp,
4603                            const struct brcmf_event_msg *e, void *data)
4604{
4605        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4606        struct net_device *ndev = ifp->ndev;
4607        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4608        s32 err = 0;
4609
4610        if (ifp->vif->mode == WL_MODE_AP) {
4611                err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
4612        } else if (brcmf_is_linkup(e)) {
4613                brcmf_dbg(CONN, "Linkup\n");
4614                if (brcmf_is_ibssmode(ifp->vif)) {
4615                        memcpy(profile->bssid, e->addr, ETH_ALEN);
4616                        wl_inform_ibss(cfg, ndev, e->addr);
4617                        cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
4618                        clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4619                                  &ifp->vif->sme_state);
4620                        set_bit(BRCMF_VIF_STATUS_CONNECTED,
4621                                &ifp->vif->sme_state);
4622                } else
4623                        brcmf_bss_connect_done(cfg, ndev, e, true);
4624        } else if (brcmf_is_linkdown(e)) {
4625                brcmf_dbg(CONN, "Linkdown\n");
4626                if (!brcmf_is_ibssmode(ifp->vif)) {
4627                        brcmf_bss_connect_done(cfg, ndev, e, false);
4628                        if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
4629                                               &ifp->vif->sme_state))
4630                                cfg80211_disconnected(ndev, 0, NULL, 0,
4631                                                      GFP_KERNEL);
4632                }
4633                brcmf_link_down(ifp->vif);
4634                brcmf_init_prof(ndev_to_prof(ndev));
4635                if (ndev != cfg_to_ndev(cfg))
4636                        complete(&cfg->vif_disabled);
4637        } else if (brcmf_is_nonetwork(cfg, e)) {
4638                if (brcmf_is_ibssmode(ifp->vif))
4639                        clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4640                                  &ifp->vif->sme_state);
4641                else
4642                        brcmf_bss_connect_done(cfg, ndev, e, false);
4643        }
4644
4645        return err;
4646}
4647
4648static s32
4649brcmf_notify_roaming_status(struct brcmf_if *ifp,
4650                            const struct brcmf_event_msg *e, void *data)
4651{
4652        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4653        s32 err = 0;
4654        u32 event = e->event_code;
4655        u32 status = e->status;
4656
4657        if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
4658                if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
4659                        brcmf_bss_roaming_done(cfg, ifp->ndev, e);
4660                else
4661                        brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
4662        }
4663
4664        return err;
4665}
4666
4667static s32
4668brcmf_notify_mic_status(struct brcmf_if *ifp,
4669                        const struct brcmf_event_msg *e, void *data)
4670{
4671        u16 flags = e->flags;
4672        enum nl80211_key_type key_type;
4673
4674        if (flags & BRCMF_EVENT_MSG_GROUP)
4675                key_type = NL80211_KEYTYPE_GROUP;
4676        else
4677                key_type = NL80211_KEYTYPE_PAIRWISE;
4678
4679        cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
4680                                     NULL, GFP_KERNEL);
4681
4682        return 0;
4683}
4684
4685static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
4686                                  const struct brcmf_event_msg *e, void *data)
4687{
4688        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4689        struct brcmf_if_event *ifevent = (struct brcmf_if_event *)data;
4690        struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
4691        struct brcmf_cfg80211_vif *vif;
4692
4693        brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfg %u\n",
4694                  ifevent->action, ifevent->flags, ifevent->ifidx,
4695                  ifevent->bssidx);
4696
4697        mutex_lock(&event->vif_event_lock);
4698        event->action = ifevent->action;
4699        vif = event->vif;
4700
4701        switch (ifevent->action) {
4702        case BRCMF_E_IF_ADD:
4703                /* waiting process may have timed out */
4704                if (!cfg->vif_event.vif) {
4705                        mutex_unlock(&event->vif_event_lock);
4706                        return -EBADF;
4707                }
4708
4709                ifp->vif = vif;
4710                vif->ifp = ifp;
4711                if (ifp->ndev) {
4712                        vif->wdev.netdev = ifp->ndev;
4713                        ifp->ndev->ieee80211_ptr = &vif->wdev;
4714                        SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
4715                }
4716                mutex_unlock(&event->vif_event_lock);
4717                wake_up(&event->vif_wq);
4718                return 0;
4719
4720        case BRCMF_E_IF_DEL:
4721                mutex_unlock(&event->vif_event_lock);
4722                /* event may not be upon user request */
4723                if (brcmf_cfg80211_vif_event_armed(cfg))
4724                        wake_up(&event->vif_wq);
4725                return 0;
4726
4727        case BRCMF_E_IF_CHANGE:
4728                mutex_unlock(&event->vif_event_lock);
4729                wake_up(&event->vif_wq);
4730                return 0;
4731
4732        default:
4733                mutex_unlock(&event->vif_event_lock);
4734                break;
4735        }
4736        return -EINVAL;
4737}
4738
4739static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
4740{
4741        conf->frag_threshold = (u32)-1;
4742        conf->rts_threshold = (u32)-1;
4743        conf->retry_short = (u32)-1;
4744        conf->retry_long = (u32)-1;
4745        conf->tx_power = -1;
4746}
4747
4748static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
4749{
4750        brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,
4751                            brcmf_notify_connect_status);
4752        brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,
4753                            brcmf_notify_connect_status);
4754        brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,
4755                            brcmf_notify_connect_status);
4756        brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,
4757                            brcmf_notify_connect_status);
4758        brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,
4759                            brcmf_notify_connect_status);
4760        brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,
4761                            brcmf_notify_connect_status);
4762        brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,
4763                            brcmf_notify_roaming_status);
4764        brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,
4765                            brcmf_notify_mic_status);
4766        brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,
4767                            brcmf_notify_connect_status);
4768        brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
4769                            brcmf_notify_sched_scan_results);
4770        brcmf_fweh_register(cfg->pub, BRCMF_E_IF,
4771                            brcmf_notify_vif_event);
4772        brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_PROBEREQ_MSG,
4773                            brcmf_p2p_notify_rx_mgmt_p2p_probereq);
4774        brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE,
4775                            brcmf_p2p_notify_listen_complete);
4776        brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,
4777                            brcmf_p2p_notify_action_frame_rx);
4778        brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_COMPLETE,
4779                            brcmf_p2p_notify_action_tx_complete);
4780        brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,
4781                            brcmf_p2p_notify_action_tx_complete);
4782}
4783
4784static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
4785{
4786        kfree(cfg->conf);
4787        cfg->conf = NULL;
4788        kfree(cfg->escan_ioctl_buf);
4789        cfg->escan_ioctl_buf = NULL;
4790        kfree(cfg->extra_buf);
4791        cfg->extra_buf = NULL;
4792        kfree(cfg->pmk_list);
4793        cfg->pmk_list = NULL;
4794}
4795
4796static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
4797{
4798        cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
4799        if (!cfg->conf)
4800                goto init_priv_mem_out;
4801        cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4802        if (!cfg->escan_ioctl_buf)
4803                goto init_priv_mem_out;
4804        cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
4805        if (!cfg->extra_buf)
4806                goto init_priv_mem_out;
4807        cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
4808        if (!cfg->pmk_list)
4809                goto init_priv_mem_out;
4810
4811        return 0;
4812
4813init_priv_mem_out:
4814        brcmf_deinit_priv_mem(cfg);
4815
4816        return -ENOMEM;
4817}
4818
4819static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
4820{
4821        s32 err = 0;
4822
4823        cfg->scan_request = NULL;
4824        cfg->pwr_save = true;
4825        cfg->roam_on = true;    /* roam on & off switch.
4826                                 we enable roam per default */
4827        cfg->active_scan = true;        /* we do active scan for
4828                                 specific scan per default */
4829        cfg->dongle_up = false; /* dongle is not up yet */
4830        err = brcmf_init_priv_mem(cfg);
4831        if (err)
4832                return err;
4833        brcmf_register_event_handlers(cfg);
4834        mutex_init(&cfg->usr_sync);
4835        brcmf_init_escan(cfg);
4836        brcmf_init_conf(cfg->conf);
4837        init_completion(&cfg->vif_disabled);
4838        return err;
4839}
4840
4841static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
4842{
4843        cfg->dongle_up = false; /* dongle down */
4844        brcmf_abort_scanning(cfg);
4845        brcmf_deinit_priv_mem(cfg);
4846}
4847
4848static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
4849{
4850        init_waitqueue_head(&event->vif_wq);
4851        mutex_init(&event->vif_event_lock);
4852}
4853
4854struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
4855                                                  struct device *busdev)
4856{
4857        struct net_device *ndev = drvr->iflist[0]->ndev;
4858        struct brcmf_cfg80211_info *cfg;
4859        struct wiphy *wiphy;
4860        struct brcmf_cfg80211_vif *vif;
4861        struct brcmf_if *ifp;
4862        s32 err = 0;
4863        s32 io_type;
4864
4865        if (!ndev) {
4866                brcmf_err("ndev is invalid\n");
4867                return NULL;
4868        }
4869
4870        ifp = netdev_priv(ndev);
4871        wiphy = brcmf_setup_wiphy(busdev);
4872        if (IS_ERR(wiphy))
4873                return NULL;
4874
4875        cfg = wiphy_priv(wiphy);
4876        cfg->wiphy = wiphy;
4877        cfg->pub = drvr;
4878        init_vif_event(&cfg->vif_event);
4879        INIT_LIST_HEAD(&cfg->vif_list);
4880
4881        vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
4882        if (IS_ERR(vif)) {
4883                wiphy_free(wiphy);
4884                return NULL;
4885        }
4886
4887        vif->ifp = ifp;
4888        vif->wdev.netdev = ndev;
4889        ndev->ieee80211_ptr = &vif->wdev;
4890        SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
4891
4892        err = wl_init_priv(cfg);
4893        if (err) {
4894                brcmf_err("Failed to init iwm_priv (%d)\n", err);
4895                goto cfg80211_attach_out;
4896        }
4897        ifp->vif = vif;
4898
4899        err = brcmf_p2p_attach(cfg);
4900        if (err) {
4901                brcmf_err("P2P initilisation failed (%d)\n", err);
4902                goto cfg80211_p2p_attach_out;
4903        }
4904        err = brcmf_btcoex_attach(cfg);
4905        if (err) {
4906                brcmf_err("BT-coex initialisation failed (%d)\n", err);
4907                brcmf_p2p_detach(&cfg->p2p);
4908                goto cfg80211_p2p_attach_out;
4909        }
4910
4911        err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
4912                                    &io_type);
4913        if (err) {
4914                brcmf_err("Failed to get D11 version (%d)\n", err);
4915                goto cfg80211_p2p_attach_out;
4916        }
4917        cfg->d11inf.io_type = (u8)io_type;
4918        brcmu_d11_attach(&cfg->d11inf);
4919
4920        return cfg;
4921
4922cfg80211_p2p_attach_out:
4923        wl_deinit_priv(cfg);
4924
4925cfg80211_attach_out:
4926        brcmf_free_vif(cfg, vif);
4927        return NULL;
4928}
4929
4930void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
4931{
4932        struct brcmf_cfg80211_vif *vif;
4933        struct brcmf_cfg80211_vif *tmp;
4934
4935        wl_deinit_priv(cfg);
4936        brcmf_btcoex_detach(cfg);
4937        list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
4938                brcmf_free_vif(cfg, vif);
4939        }
4940}
4941
4942static s32
4943brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout)
4944{
4945        s32 err = 0;
4946        __le32 roamtrigger[2];
4947        __le32 roam_delta[2];
4948
4949        /*
4950         * Setup timeout if Beacons are lost and roam is
4951         * off to report link down
4952         */
4953        if (roamvar) {
4954                err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
4955                if (err) {
4956                        brcmf_err("bcn_timeout error (%d)\n", err);
4957                        goto dongle_rom_out;
4958                }
4959        }
4960
4961        /*
4962         * Enable/Disable built-in roaming to allow supplicant
4963         * to take care of roaming
4964         */
4965        brcmf_dbg(INFO, "Internal Roaming = %s\n", roamvar ? "Off" : "On");
4966        err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
4967        if (err) {
4968                brcmf_err("roam_off error (%d)\n", err);
4969                goto dongle_rom_out;
4970        }
4971
4972        roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
4973        roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
4974        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
4975                                     (void *)roamtrigger, sizeof(roamtrigger));
4976        if (err) {
4977                brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
4978                goto dongle_rom_out;
4979        }
4980
4981        roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
4982        roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
4983        err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
4984                                     (void *)roam_delta, sizeof(roam_delta));
4985        if (err) {
4986                brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
4987                goto dongle_rom_out;
4988        }
4989
4990dongle_rom_out:
4991        return err;
4992}
4993
4994static s32
4995brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
4996                      s32 scan_unassoc_time, s32 scan_passive_time)
4997{
4998        s32 err = 0;
4999
5000        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
5001                                    scan_assoc_time);
5002        if (err) {
5003                if (err == -EOPNOTSUPP)
5004                        brcmf_dbg(INFO, "Scan assoc time is not supported\n");
5005                else
5006                        brcmf_err("Scan assoc time error (%d)\n", err);
5007                goto dongle_scantime_out;
5008        }
5009        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
5010                                    scan_unassoc_time);
5011        if (err) {
5012                if (err == -EOPNOTSUPP)
5013                        brcmf_dbg(INFO, "Scan unassoc time is not supported\n");
5014                else
5015                        brcmf_err("Scan unassoc time error (%d)\n", err);
5016                goto dongle_scantime_out;
5017        }
5018
5019        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
5020                                    scan_passive_time);
5021        if (err) {
5022                if (err == -EOPNOTSUPP)
5023                        brcmf_dbg(INFO, "Scan passive time is not supported\n");
5024                else
5025                        brcmf_err("Scan passive time error (%d)\n", err);
5026                goto dongle_scantime_out;
5027        }
5028
5029dongle_scantime_out:
5030        return err;
5031}
5032
5033
5034static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
5035{
5036        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5037        struct ieee80211_channel *band_chan_arr;
5038        struct brcmf_chanspec_list *list;
5039        struct brcmu_chan ch;
5040        s32 err;
5041        u8 *pbuf;
5042        u32 i, j;
5043        u32 total;
5044        enum ieee80211_band band;
5045        u32 channel;
5046        u32 *n_cnt;
5047        bool ht40_allowed;
5048        u32 index;
5049        u32 ht40_flag;
5050        bool update;
5051        u32 array_size;
5052
5053        pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
5054
5055        if (pbuf == NULL)
5056                return -ENOMEM;
5057
5058        list = (struct brcmf_chanspec_list *)pbuf;
5059
5060        err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
5061                                       BRCMF_DCMD_MEDLEN);
5062        if (err) {
5063                brcmf_err("get chanspecs error (%d)\n", err);
5064                goto exit;
5065        }
5066
5067        __wl_band_2ghz.n_channels = 0;
5068        __wl_band_5ghz_a.n_channels = 0;
5069
5070        total = le32_to_cpu(list->count);
5071        for (i = 0; i < total; i++) {
5072                ch.chspec = (u16)le32_to_cpu(list->element[i]);
5073                cfg->d11inf.decchspec(&ch);
5074
5075                if (ch.band == BRCMU_CHAN_BAND_2G) {
5076                        band_chan_arr = __wl_2ghz_channels;
5077                        array_size = ARRAY_SIZE(__wl_2ghz_channels);
5078                        n_cnt = &__wl_band_2ghz.n_channels;
5079                        band = IEEE80211_BAND_2GHZ;
5080                        ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
5081                } else if (ch.band == BRCMU_CHAN_BAND_5G) {
5082                        band_chan_arr = __wl_5ghz_a_channels;
5083                        array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
5084                        n_cnt = &__wl_band_5ghz_a.n_channels;
5085                        band = IEEE80211_BAND_5GHZ;
5086                        ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
5087                } else {
5088                        brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec);
5089                        continue;
5090                }
5091                if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40)
5092                        continue;
5093                update = false;
5094                for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
5095                        if (band_chan_arr[j].hw_value == ch.chnum) {
5096                                update = true;
5097                                break;
5098                        }
5099                }
5100                if (update)
5101                        index = j;
5102                else
5103                        index = *n_cnt;
5104                if (index <  array_size) {
5105                        band_chan_arr[index].center_freq =
5106                                ieee80211_channel_to_frequency(ch.chnum, band);
5107                        band_chan_arr[index].hw_value = ch.chnum;
5108
5109                        if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) {
5110                                /* assuming the order is HT20, HT40 Upper,
5111                                 * HT40 lower from chanspecs
5112                                 */
5113                                ht40_flag = band_chan_arr[index].flags &
5114                                            IEEE80211_CHAN_NO_HT40;
5115                                if (ch.sb == BRCMU_CHAN_SB_U) {
5116                                        if (ht40_flag == IEEE80211_CHAN_NO_HT40)
5117                                                band_chan_arr[index].flags &=
5118                                                        ~IEEE80211_CHAN_NO_HT40;
5119                                        band_chan_arr[index].flags |=
5120                                                IEEE80211_CHAN_NO_HT40PLUS;
5121                                } else {
5122                                        /* It should be one of
5123                                         * IEEE80211_CHAN_NO_HT40 or
5124                                         * IEEE80211_CHAN_NO_HT40PLUS
5125                                         */
5126                                        band_chan_arr[index].flags &=
5127                                                        ~IEEE80211_CHAN_NO_HT40;
5128                                        if (ht40_flag == IEEE80211_CHAN_NO_HT40)
5129                                                band_chan_arr[index].flags |=
5130                                                    IEEE80211_CHAN_NO_HT40MINUS;
5131                                }
5132                        } else {
5133                                band_chan_arr[index].flags =
5134                                                        IEEE80211_CHAN_NO_HT40;
5135                                ch.bw = BRCMU_CHAN_BW_20;
5136                                cfg->d11inf.encchspec(&ch);
5137                                channel = ch.chspec;
5138                                err = brcmf_fil_bsscfg_int_get(ifp,
5139                                                               "per_chan_info",
5140                                                               &channel);
5141                                if (!err) {
5142                                        if (channel & WL_CHAN_RADAR)
5143                                                band_chan_arr[index].flags |=
5144                                                        (IEEE80211_CHAN_RADAR |
5145                                                        IEEE80211_CHAN_NO_IBSS);
5146                                        if (channel & WL_CHAN_PASSIVE)
5147                                                band_chan_arr[index].flags |=
5148                                                    IEEE80211_CHAN_PASSIVE_SCAN;
5149                                }
5150                        }
5151                        if (!update)
5152                                (*n_cnt)++;
5153                }
5154        }
5155exit:
5156        kfree(pbuf);
5157        return err;
5158}
5159
5160
5161static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
5162{
5163        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5164        struct wiphy *wiphy;
5165        s32 phy_list;
5166        u32 band_list[3];
5167        u32 nmode;
5168        u32 bw_cap = 0;
5169        s8 phy;
5170        s32 err;
5171        u32 nband;
5172        s32 i;
5173        struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
5174        s32 index;
5175
5176        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
5177                                     &phy_list, sizeof(phy_list));
5178        if (err) {
5179                brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
5180                return err;
5181        }
5182
5183        phy = ((char *)&phy_list)[0];
5184        brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
5185
5186
5187        err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
5188                                     &band_list, sizeof(band_list));
5189        if (err) {
5190                brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
5191                return err;
5192        }
5193        brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
5194                  band_list[0], band_list[1], band_list[2]);
5195
5196        err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
5197        if (err) {
5198                brcmf_err("nmode error (%d)\n", err);
5199        } else {
5200                err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap);
5201                if (err)
5202                        brcmf_err("mimo_bw_cap error (%d)\n", err);
5203        }
5204        brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap);
5205
5206        err = brcmf_construct_reginfo(cfg, bw_cap);
5207        if (err) {
5208                brcmf_err("brcmf_construct_reginfo failed (%d)\n", err);
5209                return err;
5210        }
5211
5212        nband = band_list[0];
5213        memset(bands, 0, sizeof(bands));
5214
5215        for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
5216                index = -1;
5217                if ((band_list[i] == WLC_BAND_5G) &&
5218                    (__wl_band_5ghz_a.n_channels > 0)) {
5219                        index = IEEE80211_BAND_5GHZ;
5220                        bands[index] = &__wl_band_5ghz_a;
5221                        if ((bw_cap == WLC_N_BW_40ALL) ||
5222                            (bw_cap == WLC_N_BW_20IN2G_40IN5G))
5223                                bands[index]->ht_cap.cap |=
5224                                                        IEEE80211_HT_CAP_SGI_40;
5225                } else if ((band_list[i] == WLC_BAND_2G) &&
5226                           (__wl_band_2ghz.n_channels > 0)) {
5227                        index = IEEE80211_BAND_2GHZ;
5228                        bands[index] = &__wl_band_2ghz;
5229                        if (bw_cap == WLC_N_BW_40ALL)
5230                                bands[index]->ht_cap.cap |=
5231                                                        IEEE80211_HT_CAP_SGI_40;
5232                }
5233
5234                if ((index >= 0) && nmode) {
5235                        bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
5236                        bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
5237                        bands[index]->ht_cap.ht_supported = true;
5238                        bands[index]->ht_cap.ampdu_factor =
5239                                                IEEE80211_HT_MAX_AMPDU_64K;
5240                        bands[index]->ht_cap.ampdu_density =
5241                                                IEEE80211_HT_MPDU_DENSITY_16;
5242                        /* An HT shall support all EQM rates for one spatial
5243                         * stream
5244                         */
5245                        bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
5246                }
5247        }
5248
5249        wiphy = cfg_to_wiphy(cfg);
5250        wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
5251        wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
5252        wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5253
5254        return err;
5255}
5256
5257
5258static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
5259{
5260        return brcmf_update_wiphybands(cfg);
5261}
5262
5263static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
5264{
5265        struct net_device *ndev;
5266        struct wireless_dev *wdev;
5267        struct brcmf_if *ifp;
5268        s32 power_mode;
5269        s32 err = 0;
5270
5271        if (cfg->dongle_up)
5272                return err;
5273
5274        ndev = cfg_to_ndev(cfg);
5275        wdev = ndev->ieee80211_ptr;
5276        ifp = netdev_priv(ndev);
5277
5278        /* make sure RF is ready for work */
5279        brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
5280
5281        brcmf_dongle_scantime(ifp, WL_SCAN_CHANNEL_TIME,
5282                              WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
5283
5284        power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
5285        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
5286        if (err)
5287                goto default_conf_out;
5288        brcmf_dbg(INFO, "power save set to %s\n",
5289                  (power_mode ? "enabled" : "disabled"));
5290
5291        err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT);
5292        if (err)
5293                goto default_conf_out;
5294        err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
5295                                          NULL, NULL);
5296        if (err)
5297                goto default_conf_out;
5298        err = brcmf_dongle_probecap(cfg);
5299        if (err)
5300                goto default_conf_out;
5301
5302        brcmf_configure_arp_offload(ifp, true);
5303
5304        cfg->dongle_up = true;
5305default_conf_out:
5306
5307        return err;
5308
5309}
5310
5311static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
5312{
5313        set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
5314
5315        return brcmf_config_dongle(ifp->drvr->config);
5316}
5317
5318static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
5319{
5320        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
5321
5322        /*
5323         * While going down, if associated with AP disassociate
5324         * from AP to save power
5325         */
5326        if (check_vif_up(ifp->vif)) {
5327                brcmf_link_down(ifp->vif);
5328
5329                /* Make sure WPA_Supplicant receives all the event
5330                   generated due to DISASSOC call to the fw to keep
5331                   the state fw and WPA_Supplicant state consistent
5332                 */
5333                brcmf_delay(500);
5334        }
5335
5336        brcmf_abort_scanning(cfg);
5337        clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
5338
5339        return 0;
5340}
5341
5342s32 brcmf_cfg80211_up(struct net_device *ndev)
5343{
5344        struct brcmf_if *ifp = netdev_priv(ndev);
5345        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
5346        s32 err = 0;
5347
5348        mutex_lock(&cfg->usr_sync);
5349        err = __brcmf_cfg80211_up(ifp);
5350        mutex_unlock(&cfg->usr_sync);
5351
5352        return err;
5353}
5354
5355s32 brcmf_cfg80211_down(struct net_device *ndev)
5356{
5357        struct brcmf_if *ifp = netdev_priv(ndev);
5358        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
5359        s32 err = 0;
5360
5361        mutex_lock(&cfg->usr_sync);
5362        err = __brcmf_cfg80211_down(ifp);
5363        mutex_unlock(&cfg->usr_sync);
5364
5365        return err;
5366}
5367
5368enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
5369{
5370        struct wireless_dev *wdev = &ifp->vif->wdev;
5371
5372        return wdev->iftype;
5373}
5374
5375u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
5376{
5377        struct brcmf_cfg80211_vif *vif;
5378        bool result = 0;
5379
5380        list_for_each_entry(vif, &cfg->vif_list, list) {
5381                if (test_bit(state, &vif->sme_state))
5382                        result++;
5383        }
5384        return result;
5385}
5386
5387static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event,
5388                                    u8 action)
5389{
5390        u8 evt_action;
5391
5392        mutex_lock(&event->vif_event_lock);
5393        evt_action = event->action;
5394        mutex_unlock(&event->vif_event_lock);
5395        return evt_action == action;
5396}
5397
5398void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
5399                                  struct brcmf_cfg80211_vif *vif)
5400{
5401        struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
5402
5403        mutex_lock(&event->vif_event_lock);
5404        event->vif = vif;
5405        event->action = 0;
5406        mutex_unlock(&event->vif_event_lock);
5407}
5408
5409bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg)
5410{
5411        struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
5412        bool armed;
5413
5414        mutex_lock(&event->vif_event_lock);
5415        armed = event->vif != NULL;
5416        mutex_unlock(&event->vif_event_lock);
5417
5418        return armed;
5419}
5420int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
5421                                          u8 action, ulong timeout)
5422{
5423        struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
5424
5425        return wait_event_timeout(event->vif_wq,
5426                                  vif_event_equals(event, action), timeout);
5427}
5428
5429