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