linux/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010 Broadcom Corporation
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
  18
  19#include <linux/kernel.h>
  20#include <linux/if_arp.h>
  21#include <linux/sched.h>
  22#include <linux/kthread.h>
  23#include <linux/netdevice.h>
  24#include <linux/bitops.h>
  25#include <linux/etherdevice.h>
  26#include <linux/ieee80211.h>
  27#include <linux/uaccess.h>
  28#include <net/cfg80211.h>
  29
  30#include <brcmu_utils.h>
  31#include <defs.h>
  32#include <brcmu_wifi.h>
  33#include "dhd.h"
  34#include "wl_cfg80211.h"
  35
  36#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
  37        (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
  38
  39static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
  40
  41static u32 brcmf_dbg_level = WL_DBG_ERR;
  42
  43static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
  44{
  45        dev->driver_data = data;
  46}
  47
  48static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
  49{
  50        void *data = NULL;
  51
  52        if (dev)
  53                data = dev->driver_data;
  54        return data;
  55}
  56
  57static
  58struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev)
  59{
  60        struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev);
  61        return ci->cfg_priv;
  62}
  63
  64static bool check_sys_up(struct wiphy *wiphy)
  65{
  66        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
  67        if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
  68                WL_INFO("device is not ready : status (%d)\n",
  69                        (int)cfg_priv->status);
  70                return false;
  71        }
  72        return true;
  73}
  74
  75#define CHAN2G(_channel, _freq, _flags) {                       \
  76        .band                   = IEEE80211_BAND_2GHZ,          \
  77        .center_freq            = (_freq),                      \
  78        .hw_value               = (_channel),                   \
  79        .flags                  = (_flags),                     \
  80        .max_antenna_gain       = 0,                            \
  81        .max_power              = 30,                           \
  82}
  83
  84#define CHAN5G(_channel, _flags) {                              \
  85        .band                   = IEEE80211_BAND_5GHZ,          \
  86        .center_freq            = 5000 + (5 * (_channel)),      \
  87        .hw_value               = (_channel),                   \
  88        .flags                  = (_flags),                     \
  89        .max_antenna_gain       = 0,                            \
  90        .max_power              = 30,                           \
  91}
  92
  93#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
  94#define RATETAB_ENT(_rateid, _flags) \
  95        {                                                               \
  96                .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
  97                .hw_value       = (_rateid),                            \
  98                .flags          = (_flags),                             \
  99        }
 100
 101static struct ieee80211_rate __wl_rates[] = {
 102        RATETAB_ENT(BRCM_RATE_1M, 0),
 103        RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
 104        RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
 105        RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
 106        RATETAB_ENT(BRCM_RATE_6M, 0),
 107        RATETAB_ENT(BRCM_RATE_9M, 0),
 108        RATETAB_ENT(BRCM_RATE_12M, 0),
 109        RATETAB_ENT(BRCM_RATE_18M, 0),
 110        RATETAB_ENT(BRCM_RATE_24M, 0),
 111        RATETAB_ENT(BRCM_RATE_36M, 0),
 112        RATETAB_ENT(BRCM_RATE_48M, 0),
 113        RATETAB_ENT(BRCM_RATE_54M, 0),
 114};
 115
 116#define wl_a_rates              (__wl_rates + 4)
 117#define wl_a_rates_size 8
 118#define wl_g_rates              (__wl_rates + 0)
 119#define wl_g_rates_size 12
 120
 121static struct ieee80211_channel __wl_2ghz_channels[] = {
 122        CHAN2G(1, 2412, 0),
 123        CHAN2G(2, 2417, 0),
 124        CHAN2G(3, 2422, 0),
 125        CHAN2G(4, 2427, 0),
 126        CHAN2G(5, 2432, 0),
 127        CHAN2G(6, 2437, 0),
 128        CHAN2G(7, 2442, 0),
 129        CHAN2G(8, 2447, 0),
 130        CHAN2G(9, 2452, 0),
 131        CHAN2G(10, 2457, 0),
 132        CHAN2G(11, 2462, 0),
 133        CHAN2G(12, 2467, 0),
 134        CHAN2G(13, 2472, 0),
 135        CHAN2G(14, 2484, 0),
 136};
 137
 138static struct ieee80211_channel __wl_5ghz_a_channels[] = {
 139        CHAN5G(34, 0), CHAN5G(36, 0),
 140        CHAN5G(38, 0), CHAN5G(40, 0),
 141        CHAN5G(42, 0), CHAN5G(44, 0),
 142        CHAN5G(46, 0), CHAN5G(48, 0),
 143        CHAN5G(52, 0), CHAN5G(56, 0),
 144        CHAN5G(60, 0), CHAN5G(64, 0),
 145        CHAN5G(100, 0), CHAN5G(104, 0),
 146        CHAN5G(108, 0), CHAN5G(112, 0),
 147        CHAN5G(116, 0), CHAN5G(120, 0),
 148        CHAN5G(124, 0), CHAN5G(128, 0),
 149        CHAN5G(132, 0), CHAN5G(136, 0),
 150        CHAN5G(140, 0), CHAN5G(149, 0),
 151        CHAN5G(153, 0), CHAN5G(157, 0),
 152        CHAN5G(161, 0), CHAN5G(165, 0),
 153        CHAN5G(184, 0), CHAN5G(188, 0),
 154        CHAN5G(192, 0), CHAN5G(196, 0),
 155        CHAN5G(200, 0), CHAN5G(204, 0),
 156        CHAN5G(208, 0), CHAN5G(212, 0),
 157        CHAN5G(216, 0),
 158};
 159
 160static struct ieee80211_channel __wl_5ghz_n_channels[] = {
 161        CHAN5G(32, 0), CHAN5G(34, 0),
 162        CHAN5G(36, 0), CHAN5G(38, 0),
 163        CHAN5G(40, 0), CHAN5G(42, 0),
 164        CHAN5G(44, 0), CHAN5G(46, 0),
 165        CHAN5G(48, 0), CHAN5G(50, 0),
 166        CHAN5G(52, 0), CHAN5G(54, 0),
 167        CHAN5G(56, 0), CHAN5G(58, 0),
 168        CHAN5G(60, 0), CHAN5G(62, 0),
 169        CHAN5G(64, 0), CHAN5G(66, 0),
 170        CHAN5G(68, 0), CHAN5G(70, 0),
 171        CHAN5G(72, 0), CHAN5G(74, 0),
 172        CHAN5G(76, 0), CHAN5G(78, 0),
 173        CHAN5G(80, 0), CHAN5G(82, 0),
 174        CHAN5G(84, 0), CHAN5G(86, 0),
 175        CHAN5G(88, 0), CHAN5G(90, 0),
 176        CHAN5G(92, 0), CHAN5G(94, 0),
 177        CHAN5G(96, 0), CHAN5G(98, 0),
 178        CHAN5G(100, 0), CHAN5G(102, 0),
 179        CHAN5G(104, 0), CHAN5G(106, 0),
 180        CHAN5G(108, 0), CHAN5G(110, 0),
 181        CHAN5G(112, 0), CHAN5G(114, 0),
 182        CHAN5G(116, 0), CHAN5G(118, 0),
 183        CHAN5G(120, 0), CHAN5G(122, 0),
 184        CHAN5G(124, 0), CHAN5G(126, 0),
 185        CHAN5G(128, 0), CHAN5G(130, 0),
 186        CHAN5G(132, 0), CHAN5G(134, 0),
 187        CHAN5G(136, 0), CHAN5G(138, 0),
 188        CHAN5G(140, 0), CHAN5G(142, 0),
 189        CHAN5G(144, 0), CHAN5G(145, 0),
 190        CHAN5G(146, 0), CHAN5G(147, 0),
 191        CHAN5G(148, 0), CHAN5G(149, 0),
 192        CHAN5G(150, 0), CHAN5G(151, 0),
 193        CHAN5G(152, 0), CHAN5G(153, 0),
 194        CHAN5G(154, 0), CHAN5G(155, 0),
 195        CHAN5G(156, 0), CHAN5G(157, 0),
 196        CHAN5G(158, 0), CHAN5G(159, 0),
 197        CHAN5G(160, 0), CHAN5G(161, 0),
 198        CHAN5G(162, 0), CHAN5G(163, 0),
 199        CHAN5G(164, 0), CHAN5G(165, 0),
 200        CHAN5G(166, 0), CHAN5G(168, 0),
 201        CHAN5G(170, 0), CHAN5G(172, 0),
 202        CHAN5G(174, 0), CHAN5G(176, 0),
 203        CHAN5G(178, 0), CHAN5G(180, 0),
 204        CHAN5G(182, 0), CHAN5G(184, 0),
 205        CHAN5G(186, 0), CHAN5G(188, 0),
 206        CHAN5G(190, 0), CHAN5G(192, 0),
 207        CHAN5G(194, 0), CHAN5G(196, 0),
 208        CHAN5G(198, 0), CHAN5G(200, 0),
 209        CHAN5G(202, 0), CHAN5G(204, 0),
 210        CHAN5G(206, 0), CHAN5G(208, 0),
 211        CHAN5G(210, 0), CHAN5G(212, 0),
 212        CHAN5G(214, 0), CHAN5G(216, 0),
 213        CHAN5G(218, 0), CHAN5G(220, 0),
 214        CHAN5G(222, 0), CHAN5G(224, 0),
 215        CHAN5G(226, 0), CHAN5G(228, 0),
 216};
 217
 218static struct ieee80211_supported_band __wl_band_2ghz = {
 219        .band = IEEE80211_BAND_2GHZ,
 220        .channels = __wl_2ghz_channels,
 221        .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
 222        .bitrates = wl_g_rates,
 223        .n_bitrates = wl_g_rates_size,
 224};
 225
 226static struct ieee80211_supported_band __wl_band_5ghz_a = {
 227        .band = IEEE80211_BAND_5GHZ,
 228        .channels = __wl_5ghz_a_channels,
 229        .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
 230        .bitrates = wl_a_rates,
 231        .n_bitrates = wl_a_rates_size,
 232};
 233
 234static struct ieee80211_supported_band __wl_band_5ghz_n = {
 235        .band = IEEE80211_BAND_5GHZ,
 236        .channels = __wl_5ghz_n_channels,
 237        .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
 238        .bitrates = wl_a_rates,
 239        .n_bitrates = wl_a_rates_size,
 240};
 241
 242static const u32 __wl_cipher_suites[] = {
 243        WLAN_CIPHER_SUITE_WEP40,
 244        WLAN_CIPHER_SUITE_WEP104,
 245        WLAN_CIPHER_SUITE_TKIP,
 246        WLAN_CIPHER_SUITE_CCMP,
 247        WLAN_CIPHER_SUITE_AES_CMAC,
 248};
 249
 250/* tag_ID/length/value_buffer tuple */
 251struct brcmf_tlv {
 252        u8 id;
 253        u8 len;
 254        u8 data[1];
 255};
 256
 257/* Quarter dBm units to mW
 258 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
 259 * Table is offset so the last entry is largest mW value that fits in
 260 * a u16.
 261 */
 262
 263#define QDBM_OFFSET 153         /* Offset for first entry */
 264#define QDBM_TABLE_LEN 40       /* Table size */
 265
 266/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
 267 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
 268 */
 269#define QDBM_TABLE_LOW_BOUND 6493       /* Low bound */
 270
 271/* Largest mW value that will round down to the last table entry,
 272 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
 273 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
 274 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
 275 */
 276#define QDBM_TABLE_HIGH_BOUND 64938     /* High bound */
 277
 278static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
 279/* qdBm:        +0      +1      +2      +3      +4      +5      +6      +7 */
 280/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
 281/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
 282/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
 283/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
 284/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
 285};
 286
 287static u16 brcmf_qdbm_to_mw(u8 qdbm)
 288{
 289        uint factor = 1;
 290        int idx = qdbm - QDBM_OFFSET;
 291
 292        if (idx >= QDBM_TABLE_LEN)
 293                /* clamp to max u16 mW value */
 294                return 0xFFFF;
 295
 296        /* scale the qdBm index up to the range of the table 0-40
 297         * where an offset of 40 qdBm equals a factor of 10 mW.
 298         */
 299        while (idx < 0) {
 300                idx += 40;
 301                factor *= 10;
 302        }
 303
 304        /* return the mW value scaled down to the correct factor of 10,
 305         * adding in factor/2 to get proper rounding.
 306         */
 307        return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
 308}
 309
 310static u8 brcmf_mw_to_qdbm(u16 mw)
 311{
 312        u8 qdbm;
 313        int offset;
 314        uint mw_uint = mw;
 315        uint boundary;
 316
 317        /* handle boundary case */
 318        if (mw_uint <= 1)
 319                return 0;
 320
 321        offset = QDBM_OFFSET;
 322
 323        /* move mw into the range of the table */
 324        while (mw_uint < QDBM_TABLE_LOW_BOUND) {
 325                mw_uint *= 10;
 326                offset -= 40;
 327        }
 328
 329        for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
 330                boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
 331                                                    nqdBm_to_mW_map[qdbm]) / 2;
 332                if (mw_uint < boundary)
 333                        break;
 334        }
 335
 336        qdbm += (u8) offset;
 337
 338        return qdbm;
 339}
 340
 341/* function for reading/writing a single u32 from/to the dongle */
 342static int
 343brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
 344{
 345        int err;
 346        __le32 par_le = cpu_to_le32(*par);
 347
 348        err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
 349        *par = le32_to_cpu(par_le);
 350
 351        return err;
 352}
 353
 354static void convert_key_from_CPU(struct brcmf_wsec_key *key,
 355                                 struct brcmf_wsec_key_le *key_le)
 356{
 357        key_le->index = cpu_to_le32(key->index);
 358        key_le->len = cpu_to_le32(key->len);
 359        key_le->algo = cpu_to_le32(key->algo);
 360        key_le->flags = cpu_to_le32(key->flags);
 361        key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
 362        key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
 363        key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
 364        memcpy(key_le->data, key->data, sizeof(key->data));
 365        memcpy(key_le->ea, key->ea, sizeof(key->ea));
 366}
 367
 368static int send_key_to_dongle(struct net_device *ndev,
 369                              struct brcmf_wsec_key *key)
 370{
 371        int err;
 372        struct brcmf_wsec_key_le key_le;
 373
 374        convert_key_from_CPU(key, &key_le);
 375        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le));
 376        if (err)
 377                WL_ERR("WLC_SET_KEY error (%d)\n", err);
 378        return err;
 379}
 380
 381static s32
 382brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 383                         enum nl80211_iftype type, u32 *flags,
 384                         struct vif_params *params)
 385{
 386        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 387        struct wireless_dev *wdev;
 388        s32 infra = 0;
 389        s32 err = 0;
 390
 391        WL_TRACE("Enter\n");
 392        if (!check_sys_up(wiphy))
 393                return -EIO;
 394
 395        switch (type) {
 396        case NL80211_IFTYPE_MONITOR:
 397        case NL80211_IFTYPE_WDS:
 398                WL_ERR("type (%d) : currently we do not support this type\n",
 399                       type);
 400                return -EOPNOTSUPP;
 401        case NL80211_IFTYPE_ADHOC:
 402                cfg_priv->conf->mode = WL_MODE_IBSS;
 403                infra = 0;
 404                break;
 405        case NL80211_IFTYPE_STATION:
 406                cfg_priv->conf->mode = WL_MODE_BSS;
 407                infra = 1;
 408                break;
 409        default:
 410                err = -EINVAL;
 411                goto done;
 412        }
 413
 414        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
 415        if (err) {
 416                WL_ERR("WLC_SET_INFRA error (%d)\n", err);
 417                err = -EAGAIN;
 418        } else {
 419                wdev = ndev->ieee80211_ptr;
 420                wdev->iftype = type;
 421        }
 422
 423        WL_INFO("IF Type = %s\n",
 424                (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
 425
 426done:
 427        WL_TRACE("Exit\n");
 428
 429        return err;
 430}
 431
 432static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
 433{
 434        s8 buf[BRCMF_DCMD_SMLEN];
 435        u32 len;
 436        s32 err = 0;
 437        __le32 val_le;
 438
 439        val_le = cpu_to_le32(val);
 440        len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
 441                            sizeof(buf));
 442        BUG_ON(!len);
 443
 444        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
 445        if (err)
 446                WL_ERR("error (%d)\n", err);
 447
 448        return err;
 449}
 450
 451static s32
 452brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
 453{
 454        union {
 455                s8 buf[BRCMF_DCMD_SMLEN];
 456                __le32 val;
 457        } var;
 458        u32 len;
 459        u32 data_null;
 460        s32 err = 0;
 461
 462        len =
 463            brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
 464                        sizeof(var.buf));
 465        BUG_ON(!len);
 466        err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
 467        if (err)
 468                WL_ERR("error (%d)\n", err);
 469
 470        *retval = le32_to_cpu(var.val);
 471
 472        return err;
 473}
 474
 475static void brcmf_set_mpc(struct net_device *ndev, int mpc)
 476{
 477        s32 err = 0;
 478        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 479
 480        if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
 481                err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
 482                if (err) {
 483                        WL_ERR("fail to set mpc\n");
 484                        return;
 485                }
 486                WL_INFO("MPC : %d\n", mpc);
 487        }
 488}
 489
 490static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,
 491                          struct brcmf_ssid *ssid)
 492{
 493        memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
 494        params_le->bss_type = DOT11_BSSTYPE_ANY;
 495        params_le->scan_type = 0;
 496        params_le->channel_num = 0;
 497        params_le->nprobes = cpu_to_le32(-1);
 498        params_le->active_time = cpu_to_le32(-1);
 499        params_le->passive_time = cpu_to_le32(-1);
 500        params_le->home_time = cpu_to_le32(-1);
 501        if (ssid && ssid->SSID_len)
 502                memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
 503}
 504
 505static s32
 506brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
 507                    s32 paramlen, void *bufptr, s32 buflen)
 508{
 509        s32 iolen;
 510
 511        iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
 512        BUG_ON(!iolen);
 513
 514        return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
 515}
 516
 517static s32
 518brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
 519                    s32 paramlen, void *bufptr, s32 buflen)
 520{
 521        s32 iolen;
 522
 523        iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
 524        BUG_ON(!iolen);
 525
 526        return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
 527}
 528
 529static s32
 530brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
 531                struct brcmf_ssid *ssid, u16 action)
 532{
 533        s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
 534                          offsetof(struct brcmf_iscan_params_le, params_le);
 535        struct brcmf_iscan_params_le *params;
 536        s32 err = 0;
 537
 538        if (ssid && ssid->SSID_len)
 539                params_size += sizeof(struct brcmf_ssid);
 540        params = kzalloc(params_size, GFP_KERNEL);
 541        if (!params)
 542                return -ENOMEM;
 543        BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
 544
 545        wl_iscan_prep(&params->params_le, ssid);
 546
 547        params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
 548        params->action = cpu_to_le16(action);
 549        params->scan_duration = cpu_to_le16(0);
 550
 551        err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
 552                                     iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
 553        if (err) {
 554                if (err == -EBUSY)
 555                        WL_INFO("system busy : iscan canceled\n");
 556                else
 557                        WL_ERR("error (%d)\n", err);
 558        }
 559
 560        kfree(params);
 561        return err;
 562}
 563
 564static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 565{
 566        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
 567        struct net_device *ndev = cfg_to_ndev(cfg_priv);
 568        struct brcmf_ssid ssid;
 569        __le32 passive_scan;
 570        s32 err = 0;
 571
 572        /* Broadcast scan by default */
 573        memset(&ssid, 0, sizeof(ssid));
 574
 575        iscan->state = WL_ISCAN_STATE_SCANING;
 576
 577        passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
 578        err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
 579                        &passive_scan, sizeof(passive_scan));
 580        if (err) {
 581                WL_ERR("error (%d)\n", err);
 582                return err;
 583        }
 584        brcmf_set_mpc(ndev, 0);
 585        cfg_priv->iscan_kickstart = true;
 586        err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
 587        if (err) {
 588                brcmf_set_mpc(ndev, 1);
 589                cfg_priv->iscan_kickstart = false;
 590                return err;
 591        }
 592        mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
 593        iscan->timer_on = 1;
 594        return err;
 595}
 596
 597static s32
 598__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 599                   struct cfg80211_scan_request *request,
 600                   struct cfg80211_ssid *this_ssid)
 601{
 602        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 603        struct cfg80211_ssid *ssids;
 604        struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
 605        __le32 passive_scan;
 606        bool iscan_req;
 607        bool spec_scan;
 608        s32 err = 0;
 609        u32 SSID_len;
 610
 611        if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
 612                WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
 613                return -EAGAIN;
 614        }
 615        if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
 616                WL_ERR("Scanning being aborted : status (%lu)\n",
 617                       cfg_priv->status);
 618                return -EAGAIN;
 619        }
 620        if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
 621                WL_ERR("Connecting : status (%lu)\n",
 622                       cfg_priv->status);
 623                return -EAGAIN;
 624        }
 625
 626        iscan_req = false;
 627        spec_scan = false;
 628        if (request) {
 629                /* scan bss */
 630                ssids = request->ssids;
 631                if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
 632                        iscan_req = true;
 633        } else {
 634                /* scan in ibss */
 635                /* we don't do iscan in ibss */
 636                ssids = this_ssid;
 637        }
 638
 639        cfg_priv->scan_request = request;
 640        set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
 641        if (iscan_req) {
 642                err = brcmf_do_iscan(cfg_priv);
 643                if (!err)
 644                        return err;
 645                else
 646                        goto scan_out;
 647        } else {
 648                WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
 649                       ssids->ssid, ssids->ssid_len);
 650                memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
 651                SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
 652                sr->ssid_le.SSID_len = cpu_to_le32(0);
 653                if (SSID_len) {
 654                        memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
 655                        sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
 656                        spec_scan = true;
 657                } else {
 658                        WL_SCAN("Broadcast scan\n");
 659                }
 660
 661                passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
 662                err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
 663                                &passive_scan, sizeof(passive_scan));
 664                if (err) {
 665                        WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
 666                        goto scan_out;
 667                }
 668                brcmf_set_mpc(ndev, 0);
 669                err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
 670                                      sizeof(sr->ssid_le));
 671                if (err) {
 672                        if (err == -EBUSY)
 673                                WL_INFO("system busy : scan for \"%s\" "
 674                                        "canceled\n", sr->ssid_le.SSID);
 675                        else
 676                                WL_ERR("WLC_SCAN error (%d)\n", err);
 677
 678                        brcmf_set_mpc(ndev, 1);
 679                        goto scan_out;
 680                }
 681        }
 682
 683        return 0;
 684
 685scan_out:
 686        clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
 687        cfg_priv->scan_request = NULL;
 688        return err;
 689}
 690
 691static s32
 692brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 693                 struct cfg80211_scan_request *request)
 694{
 695        s32 err = 0;
 696
 697        WL_TRACE("Enter\n");
 698
 699        if (!check_sys_up(wiphy))
 700                return -EIO;
 701
 702        err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
 703        if (err)
 704                WL_ERR("scan error (%d)\n", err);
 705
 706        WL_TRACE("Exit\n");
 707        return err;
 708}
 709
 710static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
 711{
 712        s32 err = 0;
 713
 714        err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
 715        if (err)
 716                WL_ERR("Error (%d)\n", err);
 717
 718        return err;
 719}
 720
 721static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
 722{
 723        s32 err = 0;
 724
 725        err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
 726        if (err)
 727                WL_ERR("Error (%d)\n", err);
 728
 729        return err;
 730}
 731
 732static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
 733{
 734        s32 err = 0;
 735        u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
 736
 737        err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
 738        if (err) {
 739                WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
 740                return err;
 741        }
 742        return err;
 743}
 744
 745static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 746{
 747        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 748        struct net_device *ndev = cfg_to_ndev(cfg_priv);
 749        s32 err = 0;
 750
 751        WL_TRACE("Enter\n");
 752        if (!check_sys_up(wiphy))
 753                return -EIO;
 754
 755        if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
 756            (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
 757                cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
 758                err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
 759                if (!err)
 760                        goto done;
 761        }
 762        if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
 763            (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
 764                cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
 765                err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
 766                if (!err)
 767                        goto done;
 768        }
 769        if (changed & WIPHY_PARAM_RETRY_LONG
 770            && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
 771                cfg_priv->conf->retry_long = wiphy->retry_long;
 772                err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
 773                if (!err)
 774                        goto done;
 775        }
 776        if (changed & WIPHY_PARAM_RETRY_SHORT
 777            && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
 778                cfg_priv->conf->retry_short = wiphy->retry_short;
 779                err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
 780                if (!err)
 781                        goto done;
 782        }
 783
 784done:
 785        WL_TRACE("Exit\n");
 786        return err;
 787}
 788
 789static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
 790{
 791        switch (item) {
 792        case WL_PROF_SEC:
 793                return &cfg_priv->profile->sec;
 794        case WL_PROF_BSSID:
 795                return &cfg_priv->profile->bssid;
 796        case WL_PROF_SSID:
 797                return &cfg_priv->profile->ssid;
 798        }
 799        WL_ERR("invalid item (%d)\n", item);
 800        return NULL;
 801}
 802
 803static s32
 804brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
 805                  const struct brcmf_event_msg *e, void *data, s32 item)
 806{
 807        s32 err = 0;
 808        struct brcmf_ssid *ssid;
 809
 810        switch (item) {
 811        case WL_PROF_SSID:
 812                ssid = (struct brcmf_ssid *) data;
 813                memset(cfg_priv->profile->ssid.SSID, 0,
 814                       sizeof(cfg_priv->profile->ssid.SSID));
 815                memcpy(cfg_priv->profile->ssid.SSID,
 816                       ssid->SSID, ssid->SSID_len);
 817                cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
 818                break;
 819        case WL_PROF_BSSID:
 820                if (data)
 821                        memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
 822                else
 823                        memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
 824                break;
 825        case WL_PROF_SEC:
 826                memcpy(&cfg_priv->profile->sec, data,
 827                       sizeof(cfg_priv->profile->sec));
 828                break;
 829        case WL_PROF_BEACONINT:
 830                cfg_priv->profile->beacon_interval = *(u16 *)data;
 831                break;
 832        case WL_PROF_DTIMPERIOD:
 833                cfg_priv->profile->dtim_period = *(u8 *)data;
 834                break;
 835        default:
 836                WL_ERR("unsupported item (%d)\n", item);
 837                err = -EOPNOTSUPP;
 838                break;
 839        }
 840
 841        return err;
 842}
 843
 844static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
 845{
 846        memset(prof, 0, sizeof(*prof));
 847}
 848
 849static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
 850        size_t *join_params_size)
 851{
 852        u16 chanspec = 0;
 853
 854        if (ch != 0) {
 855                if (ch <= CH_MAX_2G_CHANNEL)
 856                        chanspec |= WL_CHANSPEC_BAND_2G;
 857                else
 858                        chanspec |= WL_CHANSPEC_BAND_5G;
 859
 860                chanspec |= WL_CHANSPEC_BW_20;
 861                chanspec |= WL_CHANSPEC_CTL_SB_NONE;
 862
 863                *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
 864                                     sizeof(u16);
 865
 866                chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
 867                join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
 868                join_params->params_le.chanspec_num = cpu_to_le32(1);
 869
 870                WL_CONN("join_params->params.chanspec_list[0]= %#X,"
 871                        "channel %d, chanspec %#X\n",
 872                        chanspec, ch, chanspec);
 873        }
 874}
 875
 876static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
 877{
 878        struct net_device *ndev = NULL;
 879        s32 err = 0;
 880
 881        WL_TRACE("Enter\n");
 882
 883        if (cfg_priv->link_up) {
 884                ndev = cfg_to_ndev(cfg_priv);
 885                WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
 886                err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
 887                if (err)
 888                        WL_ERR("WLC_DISASSOC failed (%d)\n", err);
 889                cfg_priv->link_up = false;
 890        }
 891        WL_TRACE("Exit\n");
 892}
 893
 894static s32
 895brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 896                      struct cfg80211_ibss_params *params)
 897{
 898        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 899        struct brcmf_join_params join_params;
 900        size_t join_params_size = 0;
 901        s32 err = 0;
 902        s32 wsec = 0;
 903        s32 bcnprd;
 904        struct brcmf_ssid ssid;
 905
 906        WL_TRACE("Enter\n");
 907        if (!check_sys_up(wiphy))
 908                return -EIO;
 909
 910        if (params->ssid)
 911                WL_CONN("SSID: %s\n", params->ssid);
 912        else {
 913                WL_CONN("SSID: NULL, Not supported\n");
 914                return -EOPNOTSUPP;
 915        }
 916
 917        set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
 918
 919        if (params->bssid)
 920                WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
 921                params->bssid[0], params->bssid[1], params->bssid[2],
 922                params->bssid[3], params->bssid[4], params->bssid[5]);
 923        else
 924                WL_CONN("No BSSID specified\n");
 925
 926        if (params->channel)
 927                WL_CONN("channel: %d\n", params->channel->center_freq);
 928        else
 929                WL_CONN("no channel specified\n");
 930
 931        if (params->channel_fixed)
 932                WL_CONN("fixed channel required\n");
 933        else
 934                WL_CONN("no fixed channel required\n");
 935
 936        if (params->ie && params->ie_len)
 937                WL_CONN("ie len: %d\n", params->ie_len);
 938        else
 939                WL_CONN("no ie specified\n");
 940
 941        if (params->beacon_interval)
 942                WL_CONN("beacon interval: %d\n", params->beacon_interval);
 943        else
 944                WL_CONN("no beacon interval specified\n");
 945
 946        if (params->basic_rates)
 947                WL_CONN("basic rates: %08X\n", params->basic_rates);
 948        else
 949                WL_CONN("no basic rates specified\n");
 950
 951        if (params->privacy)
 952                WL_CONN("privacy required\n");
 953        else
 954                WL_CONN("no privacy required\n");
 955
 956        /* Configure Privacy for starter */
 957        if (params->privacy)
 958                wsec |= WEP_ENABLED;
 959
 960        err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
 961        if (err) {
 962                WL_ERR("wsec failed (%d)\n", err);
 963                goto done;
 964        }
 965
 966        /* Configure Beacon Interval for starter */
 967        if (params->beacon_interval)
 968                bcnprd = params->beacon_interval;
 969        else
 970                bcnprd = 100;
 971
 972        err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
 973        if (err) {
 974                WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
 975                goto done;
 976        }
 977
 978        /* Configure required join parameter */
 979        memset(&join_params, 0, sizeof(struct brcmf_join_params));
 980
 981        /* SSID */
 982        ssid.SSID_len = min_t(u32, params->ssid_len, 32);
 983        memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
 984        memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len);
 985        join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
 986        join_params_size = sizeof(join_params.ssid_le);
 987        brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
 988
 989        /* BSSID */
 990        if (params->bssid) {
 991                memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
 992                join_params_size = sizeof(join_params.ssid_le) +
 993                                   BRCMF_ASSOC_PARAMS_FIXED_SIZE;
 994        } else {
 995                memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
 996        }
 997
 998        brcmf_update_prof(cfg_priv, NULL,
 999                          &join_params.params_le.bssid, WL_PROF_BSSID);
1000
1001        /* Channel */
1002        if (params->channel) {
1003                u32 target_channel;
1004
1005                cfg_priv->channel =
1006                        ieee80211_frequency_to_channel(
1007                                params->channel->center_freq);
1008                if (params->channel_fixed) {
1009                        /* adding chanspec */
1010                        brcmf_ch_to_chanspec(cfg_priv->channel,
1011                                &join_params, &join_params_size);
1012                }
1013
1014                /* set channel for starter */
1015                target_channel = cfg_priv->channel;
1016                err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
1017                                          &target_channel);
1018                if (err) {
1019                        WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
1020                        goto done;
1021                }
1022        } else
1023                cfg_priv->channel = 0;
1024
1025        cfg_priv->ibss_starter = false;
1026
1027
1028        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1029                           &join_params, join_params_size);
1030        if (err) {
1031                WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1032                goto done;
1033        }
1034
1035done:
1036        if (err)
1037                clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1038        WL_TRACE("Exit\n");
1039        return err;
1040}
1041
1042static s32
1043brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1044{
1045        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1046        s32 err = 0;
1047
1048        WL_TRACE("Enter\n");
1049        if (!check_sys_up(wiphy))
1050                return -EIO;
1051
1052        brcmf_link_down(cfg_priv);
1053
1054        WL_TRACE("Exit\n");
1055
1056        return err;
1057}
1058
1059static s32 brcmf_set_wpa_version(struct net_device *ndev,
1060                                 struct cfg80211_connect_params *sme)
1061{
1062        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1063        struct brcmf_cfg80211_security *sec;
1064        s32 val = 0;
1065        s32 err = 0;
1066
1067        if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1068                val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1069        else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1070                val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1071        else
1072                val = WPA_AUTH_DISABLED;
1073        WL_CONN("setting wpa_auth to 0x%0x\n", val);
1074        err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1075        if (err) {
1076                WL_ERR("set wpa_auth failed (%d)\n", err);
1077                return err;
1078        }
1079        sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1080        sec->wpa_versions = sme->crypto.wpa_versions;
1081        return err;
1082}
1083
1084static s32 brcmf_set_auth_type(struct net_device *ndev,
1085                               struct cfg80211_connect_params *sme)
1086{
1087        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1088        struct brcmf_cfg80211_security *sec;
1089        s32 val = 0;
1090        s32 err = 0;
1091
1092        switch (sme->auth_type) {
1093        case NL80211_AUTHTYPE_OPEN_SYSTEM:
1094                val = 0;
1095                WL_CONN("open system\n");
1096                break;
1097        case NL80211_AUTHTYPE_SHARED_KEY:
1098                val = 1;
1099                WL_CONN("shared key\n");
1100                break;
1101        case NL80211_AUTHTYPE_AUTOMATIC:
1102                val = 2;
1103                WL_CONN("automatic\n");
1104                break;
1105        case NL80211_AUTHTYPE_NETWORK_EAP:
1106                WL_CONN("network eap\n");
1107        default:
1108                val = 2;
1109                WL_ERR("invalid auth type (%d)\n", sme->auth_type);
1110                break;
1111        }
1112
1113        err = brcmf_dev_intvar_set(ndev, "auth", val);
1114        if (err) {
1115                WL_ERR("set auth failed (%d)\n", err);
1116                return err;
1117        }
1118        sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1119        sec->auth_type = sme->auth_type;
1120        return err;
1121}
1122
1123static s32
1124brcmf_set_set_cipher(struct net_device *ndev,
1125                     struct cfg80211_connect_params *sme)
1126{
1127        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1128        struct brcmf_cfg80211_security *sec;
1129        s32 pval = 0;
1130        s32 gval = 0;
1131        s32 err = 0;
1132
1133        if (sme->crypto.n_ciphers_pairwise) {
1134                switch (sme->crypto.ciphers_pairwise[0]) {
1135                case WLAN_CIPHER_SUITE_WEP40:
1136                case WLAN_CIPHER_SUITE_WEP104:
1137                        pval = WEP_ENABLED;
1138                        break;
1139                case WLAN_CIPHER_SUITE_TKIP:
1140                        pval = TKIP_ENABLED;
1141                        break;
1142                case WLAN_CIPHER_SUITE_CCMP:
1143                        pval = AES_ENABLED;
1144                        break;
1145                case WLAN_CIPHER_SUITE_AES_CMAC:
1146                        pval = AES_ENABLED;
1147                        break;
1148                default:
1149                        WL_ERR("invalid cipher pairwise (%d)\n",
1150                               sme->crypto.ciphers_pairwise[0]);
1151                        return -EINVAL;
1152                }
1153        }
1154        if (sme->crypto.cipher_group) {
1155                switch (sme->crypto.cipher_group) {
1156                case WLAN_CIPHER_SUITE_WEP40:
1157                case WLAN_CIPHER_SUITE_WEP104:
1158                        gval = WEP_ENABLED;
1159                        break;
1160                case WLAN_CIPHER_SUITE_TKIP:
1161                        gval = TKIP_ENABLED;
1162                        break;
1163                case WLAN_CIPHER_SUITE_CCMP:
1164                        gval = AES_ENABLED;
1165                        break;
1166                case WLAN_CIPHER_SUITE_AES_CMAC:
1167                        gval = AES_ENABLED;
1168                        break;
1169                default:
1170                        WL_ERR("invalid cipher group (%d)\n",
1171                               sme->crypto.cipher_group);
1172                        return -EINVAL;
1173                }
1174        }
1175
1176        WL_CONN("pval (%d) gval (%d)\n", pval, gval);
1177        err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
1178        if (err) {
1179                WL_ERR("error (%d)\n", err);
1180                return err;
1181        }
1182
1183        sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1184        sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1185        sec->cipher_group = sme->crypto.cipher_group;
1186
1187        return err;
1188}
1189
1190static s32
1191brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1192{
1193        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1194        struct brcmf_cfg80211_security *sec;
1195        s32 val = 0;
1196        s32 err = 0;
1197
1198        if (sme->crypto.n_akm_suites) {
1199                err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
1200                if (err) {
1201                        WL_ERR("could not get wpa_auth (%d)\n", err);
1202                        return err;
1203                }
1204                if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1205                        switch (sme->crypto.akm_suites[0]) {
1206                        case WLAN_AKM_SUITE_8021X:
1207                                val = WPA_AUTH_UNSPECIFIED;
1208                                break;
1209                        case WLAN_AKM_SUITE_PSK:
1210                                val = WPA_AUTH_PSK;
1211                                break;
1212                        default:
1213                                WL_ERR("invalid cipher group (%d)\n",
1214                                       sme->crypto.cipher_group);
1215                                return -EINVAL;
1216                        }
1217                } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1218                        switch (sme->crypto.akm_suites[0]) {
1219                        case WLAN_AKM_SUITE_8021X:
1220                                val = WPA2_AUTH_UNSPECIFIED;
1221                                break;
1222                        case WLAN_AKM_SUITE_PSK:
1223                                val = WPA2_AUTH_PSK;
1224                                break;
1225                        default:
1226                                WL_ERR("invalid cipher group (%d)\n",
1227                                       sme->crypto.cipher_group);
1228                                return -EINVAL;
1229                        }
1230                }
1231
1232                WL_CONN("setting wpa_auth to %d\n", val);
1233                err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1234                if (err) {
1235                        WL_ERR("could not set wpa_auth (%d)\n", err);
1236                        return err;
1237                }
1238        }
1239        sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1240        sec->wpa_auth = sme->crypto.akm_suites[0];
1241
1242        return err;
1243}
1244
1245static s32
1246brcmf_set_wep_sharedkey(struct net_device *ndev,
1247                     struct cfg80211_connect_params *sme)
1248{
1249        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1250        struct brcmf_cfg80211_security *sec;
1251        struct brcmf_wsec_key key;
1252        s32 val;
1253        s32 err = 0;
1254
1255        WL_CONN("key len (%d)\n", sme->key_len);
1256
1257        if (sme->key_len == 0)
1258                return 0;
1259
1260        sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1261        WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1262                sec->wpa_versions, sec->cipher_pairwise);
1263
1264        if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1265                return 0;
1266
1267        if (sec->cipher_pairwise &
1268            (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) {
1269                memset(&key, 0, sizeof(key));
1270                key.len = (u32) sme->key_len;
1271                key.index = (u32) sme->key_idx;
1272                if (key.len > sizeof(key.data)) {
1273                        WL_ERR("Too long key length (%u)\n", key.len);
1274                        return -EINVAL;
1275                }
1276                memcpy(key.data, sme->key, key.len);
1277                key.flags = BRCMF_PRIMARY_KEY;
1278                switch (sec->cipher_pairwise) {
1279                case WLAN_CIPHER_SUITE_WEP40:
1280                        key.algo = CRYPTO_ALGO_WEP1;
1281                        break;
1282                case WLAN_CIPHER_SUITE_WEP104:
1283                        key.algo = CRYPTO_ALGO_WEP128;
1284                        break;
1285                default:
1286                        WL_ERR("Invalid algorithm (%d)\n",
1287                               sme->crypto.ciphers_pairwise[0]);
1288                        return -EINVAL;
1289                }
1290                /* Set the new key/index */
1291                WL_CONN("key length (%d) key index (%d) algo (%d)\n",
1292                        key.len, key.index, key.algo);
1293                WL_CONN("key \"%s\"\n", key.data);
1294                err = send_key_to_dongle(ndev, &key);
1295                if (err)
1296                        return err;
1297
1298                if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
1299                        WL_CONN("set auth_type to shared key\n");
1300                        val = 1;        /* shared key */
1301                        err = brcmf_dev_intvar_set(ndev, "auth", val);
1302                        if (err) {
1303                                WL_ERR("set auth failed (%d)\n", err);
1304                                return err;
1305                        }
1306                }
1307        }
1308        return err;
1309}
1310
1311static s32
1312brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1313                    struct cfg80211_connect_params *sme)
1314{
1315        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1316        struct ieee80211_channel *chan = sme->channel;
1317        struct brcmf_join_params join_params;
1318        size_t join_params_size;
1319        struct brcmf_ssid ssid;
1320
1321        s32 err = 0;
1322
1323        WL_TRACE("Enter\n");
1324        if (!check_sys_up(wiphy))
1325                return -EIO;
1326
1327        if (!sme->ssid) {
1328                WL_ERR("Invalid ssid\n");
1329                return -EOPNOTSUPP;
1330        }
1331
1332        set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1333
1334        if (chan) {
1335                cfg_priv->channel =
1336                        ieee80211_frequency_to_channel(chan->center_freq);
1337                WL_CONN("channel (%d), center_req (%d)\n",
1338                                cfg_priv->channel, chan->center_freq);
1339        } else
1340                cfg_priv->channel = 0;
1341
1342        WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1343
1344        err = brcmf_set_wpa_version(ndev, sme);
1345        if (err) {
1346                WL_ERR("wl_set_wpa_version failed (%d)\n", err);
1347                goto done;
1348        }
1349
1350        err = brcmf_set_auth_type(ndev, sme);
1351        if (err) {
1352                WL_ERR("wl_set_auth_type failed (%d)\n", err);
1353                goto done;
1354        }
1355
1356        err = brcmf_set_set_cipher(ndev, sme);
1357        if (err) {
1358                WL_ERR("wl_set_set_cipher failed (%d)\n", err);
1359                goto done;
1360        }
1361
1362        err = brcmf_set_key_mgmt(ndev, sme);
1363        if (err) {
1364                WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
1365                goto done;
1366        }
1367
1368        err = brcmf_set_wep_sharedkey(ndev, sme);
1369        if (err) {
1370                WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err);
1371                goto done;
1372        }
1373
1374        memset(&join_params, 0, sizeof(join_params));
1375        join_params_size = sizeof(join_params.ssid_le);
1376
1377        ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len);
1378        memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
1379        memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
1380        join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
1381        brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
1382
1383        memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
1384
1385        if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
1386                WL_CONN("ssid \"%s\", len (%d)\n",
1387                       ssid.SSID, ssid.SSID_len);
1388
1389        brcmf_ch_to_chanspec(cfg_priv->channel,
1390                             &join_params, &join_params_size);
1391        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1392                           &join_params, join_params_size);
1393        if (err)
1394                WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1395
1396done:
1397        if (err)
1398                clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1399        WL_TRACE("Exit\n");
1400        return err;
1401}
1402
1403static s32
1404brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1405                       u16 reason_code)
1406{
1407        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1408        struct brcmf_scb_val_le scbval;
1409        s32 err = 0;
1410
1411        WL_TRACE("Enter. Reason code = %d\n", reason_code);
1412        if (!check_sys_up(wiphy))
1413                return -EIO;
1414
1415        clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
1416
1417        memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
1418        scbval.val = cpu_to_le32(reason_code);
1419        err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
1420                              sizeof(struct brcmf_scb_val_le));
1421        if (err)
1422                WL_ERR("error (%d)\n", err);
1423
1424        cfg_priv->link_up = false;
1425
1426        WL_TRACE("Exit\n");
1427        return err;
1428}
1429
1430static s32
1431brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
1432                         enum nl80211_tx_power_setting type, s32 dbm)
1433{
1434
1435        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1436        struct net_device *ndev = cfg_to_ndev(cfg_priv);
1437        u16 txpwrmw;
1438        s32 err = 0;
1439        s32 disable = 0;
1440
1441        WL_TRACE("Enter\n");
1442        if (!check_sys_up(wiphy))
1443                return -EIO;
1444
1445        switch (type) {
1446        case NL80211_TX_POWER_AUTOMATIC:
1447                break;
1448        case NL80211_TX_POWER_LIMITED:
1449                if (dbm < 0) {
1450                        WL_ERR("TX_POWER_LIMITED - dbm is negative\n");
1451                        err = -EINVAL;
1452                        goto done;
1453                }
1454                break;
1455        case NL80211_TX_POWER_FIXED:
1456                if (dbm < 0) {
1457                        WL_ERR("TX_POWER_FIXED - dbm is negative\n");
1458                        err = -EINVAL;
1459                        goto done;
1460                }
1461                break;
1462        }
1463        /* Make sure radio is off or on as far as software is concerned */
1464        disable = WL_RADIO_SW_DISABLE << 16;
1465        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
1466        if (err)
1467                WL_ERR("WLC_SET_RADIO error (%d)\n", err);
1468
1469        if (dbm > 0xffff)
1470                txpwrmw = 0xffff;
1471        else
1472                txpwrmw = (u16) dbm;
1473        err = brcmf_dev_intvar_set(ndev, "qtxpower",
1474                        (s32) (brcmf_mw_to_qdbm(txpwrmw)));
1475        if (err)
1476                WL_ERR("qtxpower error (%d)\n", err);
1477        cfg_priv->conf->tx_power = dbm;
1478
1479done:
1480        WL_TRACE("Exit\n");
1481        return err;
1482}
1483
1484static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
1485{
1486        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1487        struct net_device *ndev = cfg_to_ndev(cfg_priv);
1488        s32 txpwrdbm;
1489        u8 result;
1490        s32 err = 0;
1491
1492        WL_TRACE("Enter\n");
1493        if (!check_sys_up(wiphy))
1494                return -EIO;
1495
1496        err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
1497        if (err) {
1498                WL_ERR("error (%d)\n", err);
1499                goto done;
1500        }
1501
1502        result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1503        *dbm = (s32) brcmf_qdbm_to_mw(result);
1504
1505done:
1506        WL_TRACE("Exit\n");
1507        return err;
1508}
1509
1510static s32
1511brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
1512                               u8 key_idx, bool unicast, bool multicast)
1513{
1514        u32 index;
1515        u32 wsec;
1516        s32 err = 0;
1517
1518        WL_TRACE("Enter\n");
1519        WL_CONN("key index (%d)\n", key_idx);
1520        if (!check_sys_up(wiphy))
1521                return -EIO;
1522
1523        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
1524        if (err) {
1525                WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1526                goto done;
1527        }
1528
1529        if (wsec & WEP_ENABLED) {
1530                /* Just select a new current key */
1531                index = key_idx;
1532                err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
1533                                          &index);
1534                if (err)
1535                        WL_ERR("error (%d)\n", err);
1536        }
1537done:
1538        WL_TRACE("Exit\n");
1539        return err;
1540}
1541
1542static s32
1543brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
1544              u8 key_idx, const u8 *mac_addr, struct key_params *params)
1545{
1546        struct brcmf_wsec_key key;
1547        struct brcmf_wsec_key_le key_le;
1548        s32 err = 0;
1549
1550        memset(&key, 0, sizeof(key));
1551        key.index = (u32) key_idx;
1552        /* Instead of bcast for ea address for default wep keys,
1553                 driver needs it to be Null */
1554        if (!is_multicast_ether_addr(mac_addr))
1555                memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1556        key.len = (u32) params->key_len;
1557        /* check for key index change */
1558        if (key.len == 0) {
1559                /* key delete */
1560                err = send_key_to_dongle(ndev, &key);
1561                if (err)
1562                        return err;
1563        } else {
1564                if (key.len > sizeof(key.data)) {
1565                        WL_ERR("Invalid key length (%d)\n", key.len);
1566                        return -EINVAL;
1567                }
1568
1569                WL_CONN("Setting the key index %d\n", key.index);
1570                memcpy(key.data, params->key, key.len);
1571
1572                if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1573                        u8 keybuf[8];
1574                        memcpy(keybuf, &key.data[24], sizeof(keybuf));
1575                        memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1576                        memcpy(&key.data[16], keybuf, sizeof(keybuf));
1577                }
1578
1579                /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1580                if (params->seq && params->seq_len == 6) {
1581                        /* rx iv */
1582                        u8 *ivptr;
1583                        ivptr = (u8 *) params->seq;
1584                        key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1585                            (ivptr[3] << 8) | ivptr[2];
1586                        key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1587                        key.iv_initialized = true;
1588                }
1589
1590                switch (params->cipher) {
1591                case WLAN_CIPHER_SUITE_WEP40:
1592                        key.algo = CRYPTO_ALGO_WEP1;
1593                        WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1594                        break;
1595                case WLAN_CIPHER_SUITE_WEP104:
1596                        key.algo = CRYPTO_ALGO_WEP128;
1597                        WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1598                        break;
1599                case WLAN_CIPHER_SUITE_TKIP:
1600                        key.algo = CRYPTO_ALGO_TKIP;
1601                        WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1602                        break;
1603                case WLAN_CIPHER_SUITE_AES_CMAC:
1604                        key.algo = CRYPTO_ALGO_AES_CCM;
1605                        WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1606                        break;
1607                case WLAN_CIPHER_SUITE_CCMP:
1608                        key.algo = CRYPTO_ALGO_AES_CCM;
1609                        WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1610                        break;
1611                default:
1612                        WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1613                        return -EINVAL;
1614                }
1615                convert_key_from_CPU(&key, &key_le);
1616
1617                brcmf_netdev_wait_pend8021x(ndev);
1618                err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le,
1619                                      sizeof(key_le));
1620                if (err) {
1621                        WL_ERR("WLC_SET_KEY error (%d)\n", err);
1622                        return err;
1623                }
1624        }
1625        return err;
1626}
1627
1628static s32
1629brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1630                    u8 key_idx, bool pairwise, const u8 *mac_addr,
1631                    struct key_params *params)
1632{
1633        struct brcmf_wsec_key key;
1634        s32 val;
1635        s32 wsec;
1636        s32 err = 0;
1637        u8 keybuf[8];
1638
1639        WL_TRACE("Enter\n");
1640        WL_CONN("key index (%d)\n", key_idx);
1641        if (!check_sys_up(wiphy))
1642                return -EIO;
1643
1644        if (mac_addr) {
1645                WL_TRACE("Exit");
1646                return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
1647        }
1648        memset(&key, 0, sizeof(key));
1649
1650        key.len = (u32) params->key_len;
1651        key.index = (u32) key_idx;
1652
1653        if (key.len > sizeof(key.data)) {
1654                WL_ERR("Too long key length (%u)\n", key.len);
1655                err = -EINVAL;
1656                goto done;
1657        }
1658        memcpy(key.data, params->key, key.len);
1659
1660        key.flags = BRCMF_PRIMARY_KEY;
1661        switch (params->cipher) {
1662        case WLAN_CIPHER_SUITE_WEP40:
1663                key.algo = CRYPTO_ALGO_WEP1;
1664                WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1665                break;
1666        case WLAN_CIPHER_SUITE_WEP104:
1667                key.algo = CRYPTO_ALGO_WEP128;
1668                WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1669                break;
1670        case WLAN_CIPHER_SUITE_TKIP:
1671                memcpy(keybuf, &key.data[24], sizeof(keybuf));
1672                memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1673                memcpy(&key.data[16], keybuf, sizeof(keybuf));
1674                key.algo = CRYPTO_ALGO_TKIP;
1675                WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1676                break;
1677        case WLAN_CIPHER_SUITE_AES_CMAC:
1678                key.algo = CRYPTO_ALGO_AES_CCM;
1679                WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1680                break;
1681        case WLAN_CIPHER_SUITE_CCMP:
1682                key.algo = CRYPTO_ALGO_AES_CCM;
1683                WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1684                break;
1685        default:
1686                WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1687                err = -EINVAL;
1688                goto done;
1689        }
1690
1691        err = send_key_to_dongle(ndev, &key); /* Set the new key/index */
1692        if (err)
1693                goto done;
1694
1695        val = WEP_ENABLED;
1696        err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
1697        if (err) {
1698                WL_ERR("get wsec error (%d)\n", err);
1699                goto done;
1700        }
1701        wsec &= ~(WEP_ENABLED);
1702        wsec |= val;
1703        err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
1704        if (err) {
1705                WL_ERR("set wsec error (%d)\n", err);
1706                goto done;
1707        }
1708
1709        val = 1;                /* assume shared key. otherwise 0 */
1710        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
1711        if (err)
1712                WL_ERR("WLC_SET_AUTH error (%d)\n", err);
1713done:
1714        WL_TRACE("Exit\n");
1715        return err;
1716}
1717
1718static s32
1719brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1720                    u8 key_idx, bool pairwise, const u8 *mac_addr)
1721{
1722        struct brcmf_wsec_key key;
1723        s32 err = 0;
1724        s32 val;
1725        s32 wsec;
1726
1727        WL_TRACE("Enter\n");
1728        if (!check_sys_up(wiphy))
1729                return -EIO;
1730
1731        memset(&key, 0, sizeof(key));
1732
1733        key.index = (u32) key_idx;
1734        key.flags = BRCMF_PRIMARY_KEY;
1735        key.algo = CRYPTO_ALGO_OFF;
1736
1737        WL_CONN("key index (%d)\n", key_idx);
1738
1739        /* Set the new key/index */
1740        err = send_key_to_dongle(ndev, &key);
1741        if (err) {
1742                if (err == -EINVAL) {
1743                        if (key.index >= DOT11_MAX_DEFAULT_KEYS)
1744                                /* we ignore this key index in this case */
1745                                WL_ERR("invalid key index (%d)\n", key_idx);
1746                }
1747                /* Ignore this error, may happen during DISASSOC */
1748                err = -EAGAIN;
1749                goto done;
1750        }
1751
1752        val = 0;
1753        err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
1754        if (err) {
1755                WL_ERR("get wsec error (%d)\n", err);
1756                /* Ignore this error, may happen during DISASSOC */
1757                err = -EAGAIN;
1758                goto done;
1759        }
1760        wsec &= ~(WEP_ENABLED);
1761        wsec |= val;
1762        err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
1763        if (err) {
1764                WL_ERR("set wsec error (%d)\n", err);
1765                /* Ignore this error, may happen during DISASSOC */
1766                err = -EAGAIN;
1767                goto done;
1768        }
1769
1770        val = 0;                /* assume open key. otherwise 1 */
1771        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
1772        if (err) {
1773                WL_ERR("WLC_SET_AUTH error (%d)\n", err);
1774                /* Ignore this error, may happen during DISASSOC */
1775                err = -EAGAIN;
1776        }
1777done:
1778        WL_TRACE("Exit\n");
1779        return err;
1780}
1781
1782static s32
1783brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1784                    u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
1785                    void (*callback) (void *cookie, struct key_params * params))
1786{
1787        struct key_params params;
1788        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1789        struct brcmf_cfg80211_security *sec;
1790        s32 wsec;
1791        s32 err = 0;
1792
1793        WL_TRACE("Enter\n");
1794        WL_CONN("key index (%d)\n", key_idx);
1795        if (!check_sys_up(wiphy))
1796                return -EIO;
1797
1798        memset(&params, 0, sizeof(params));
1799
1800        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
1801        if (err) {
1802                WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1803                /* Ignore this error, may happen during DISASSOC */
1804                err = -EAGAIN;
1805                goto done;
1806        }
1807        switch (wsec) {
1808        case WEP_ENABLED:
1809                sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1810                if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
1811                        params.cipher = WLAN_CIPHER_SUITE_WEP40;
1812                        WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1813                } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
1814                        params.cipher = WLAN_CIPHER_SUITE_WEP104;
1815                        WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1816                }
1817                break;
1818        case TKIP_ENABLED:
1819                params.cipher = WLAN_CIPHER_SUITE_TKIP;
1820                WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1821                break;
1822        case AES_ENABLED:
1823                params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
1824                WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1825                break;
1826        default:
1827                WL_ERR("Invalid algo (0x%x)\n", wsec);
1828                err = -EINVAL;
1829                goto done;
1830        }
1831        callback(cookie, &params);
1832
1833done:
1834        WL_TRACE("Exit\n");
1835        return err;
1836}
1837
1838static s32
1839brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
1840                                    struct net_device *ndev, u8 key_idx)
1841{
1842        WL_INFO("Not supported\n");
1843
1844        return -EOPNOTSUPP;
1845}
1846
1847static s32
1848brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
1849                        u8 *mac, struct station_info *sinfo)
1850{
1851        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1852        struct brcmf_scb_val_le scb_val;
1853        int rssi;
1854        s32 rate;
1855        s32 err = 0;
1856        u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
1857
1858        WL_TRACE("Enter\n");
1859        if (!check_sys_up(wiphy))
1860                return -EIO;
1861
1862        if (memcmp(mac, bssid, ETH_ALEN)) {
1863                WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X"
1864                        "wl_bssid-%X:%X:%X:%X:%X:%X\n",
1865                        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
1866                        bssid[0], bssid[1], bssid[2], bssid[3],
1867                        bssid[4], bssid[5]);
1868                err = -ENOENT;
1869                goto done;
1870        }
1871
1872        /* Report the current tx rate */
1873        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
1874        if (err) {
1875                WL_ERR("Could not get rate (%d)\n", err);
1876        } else {
1877                sinfo->filled |= STATION_INFO_TX_BITRATE;
1878                sinfo->txrate.legacy = rate * 5;
1879                WL_CONN("Rate %d Mbps\n", rate / 2);
1880        }
1881
1882        if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
1883                scb_val.val = cpu_to_le32(0);
1884                err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
1885                                      sizeof(struct brcmf_scb_val_le));
1886                if (err)
1887                        WL_ERR("Could not get rssi (%d)\n", err);
1888
1889                rssi = le32_to_cpu(scb_val.val);
1890                sinfo->filled |= STATION_INFO_SIGNAL;
1891                sinfo->signal = rssi;
1892                WL_CONN("RSSI %d dBm\n", rssi);
1893        }
1894
1895done:
1896        WL_TRACE("Exit\n");
1897        return err;
1898}
1899
1900static s32
1901brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
1902                           bool enabled, s32 timeout)
1903{
1904        s32 pm;
1905        s32 err = 0;
1906        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1907
1908        WL_TRACE("Enter\n");
1909
1910        /*
1911         * Powersave enable/disable request is coming from the
1912         * cfg80211 even before the interface is up. In that
1913         * scenario, driver will be storing the power save
1914         * preference in cfg_priv struct to apply this to
1915         * FW later while initializing the dongle
1916         */
1917        cfg_priv->pwr_save = enabled;
1918        if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
1919
1920                WL_INFO("Device is not ready,"
1921                        "storing the value in cfg_priv struct\n");
1922                goto done;
1923        }
1924
1925        pm = enabled ? PM_FAST : PM_OFF;
1926        WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
1927
1928        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
1929        if (err) {
1930                if (err == -ENODEV)
1931                        WL_ERR("net_device is not ready yet\n");
1932                else
1933                        WL_ERR("error (%d)\n", err);
1934        }
1935done:
1936        WL_TRACE("Exit\n");
1937        return err;
1938}
1939
1940static s32
1941brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
1942                             const u8 *addr,
1943                             const struct cfg80211_bitrate_mask *mask)
1944{
1945        struct brcm_rateset_le rateset_le;
1946        s32 rate;
1947        s32 val;
1948        s32 err_bg;
1949        s32 err_a;
1950        u32 legacy;
1951        s32 err = 0;
1952
1953        WL_TRACE("Enter\n");
1954        if (!check_sys_up(wiphy))
1955                return -EIO;
1956
1957        /* addr param is always NULL. ignore it */
1958        /* Get current rateset */
1959        err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
1960                              sizeof(rateset_le));
1961        if (err) {
1962                WL_ERR("could not get current rateset (%d)\n", err);
1963                goto done;
1964        }
1965
1966        legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
1967        if (!legacy)
1968                legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
1969                             0xFFFF);
1970
1971        val = wl_g_rates[legacy - 1].bitrate * 100000;
1972
1973        if (val < le32_to_cpu(rateset_le.count))
1974                /* Select rate by rateset index */
1975                rate = rateset_le.rates[val] & 0x7f;
1976        else
1977                /* Specified rate in bps */
1978                rate = val / 500000;
1979
1980        WL_CONN("rate %d mbps\n", rate / 2);
1981
1982        /*
1983         *
1984         *      Set rate override,
1985         *      Since the is a/b/g-blind, both a/bg_rate are enforced.
1986         */
1987        err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
1988        err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
1989        if (err_bg && err_a) {
1990                WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
1991                err = err_bg | err_a;
1992        }
1993
1994done:
1995        WL_TRACE("Exit\n");
1996        return err;
1997}
1998
1999static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
2000                                   struct brcmf_bss_info *bi)
2001{
2002        struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2003        struct ieee80211_channel *notify_channel;
2004        struct cfg80211_bss *bss;
2005        struct ieee80211_supported_band *band;
2006        s32 err = 0;
2007        u16 channel;
2008        u32 freq;
2009        u64 notify_timestamp;
2010        u16 notify_capability;
2011        u16 notify_interval;
2012        u8 *notify_ie;
2013        size_t notify_ielen;
2014        s32 notify_signal;
2015
2016        if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2017                WL_ERR("Bss info is larger than buffer. Discarding\n");
2018                return 0;
2019        }
2020
2021        channel = bi->ctl_ch ? bi->ctl_ch :
2022                                CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2023
2024        if (channel <= CH_MAX_2G_CHANNEL)
2025                band = wiphy->bands[IEEE80211_BAND_2GHZ];
2026        else
2027                band = wiphy->bands[IEEE80211_BAND_5GHZ];
2028
2029        freq = ieee80211_channel_to_frequency(channel, band->band);
2030        notify_channel = ieee80211_get_channel(wiphy, freq);
2031
2032        notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
2033        notify_capability = le16_to_cpu(bi->capability);
2034        notify_interval = le16_to_cpu(bi->beacon_period);
2035        notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2036        notify_ielen = le32_to_cpu(bi->ie_length);
2037        notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2038
2039        WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2040                        bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2041                        bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2042        WL_CONN("Channel: %d(%d)\n", channel, freq);
2043        WL_CONN("Capability: %X\n", notify_capability);
2044        WL_CONN("Beacon interval: %d\n", notify_interval);
2045        WL_CONN("Signal: %d\n", notify_signal);
2046        WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
2047
2048        bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2049                notify_timestamp, notify_capability, notify_interval, notify_ie,
2050                notify_ielen, notify_signal, GFP_KERNEL);
2051
2052        if (!bss) {
2053                WL_ERR("cfg80211_inform_bss_frame error\n");
2054                return -EINVAL;
2055        }
2056
2057        return err;
2058}
2059
2060static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
2061{
2062        struct brcmf_scan_results *bss_list;
2063        struct brcmf_bss_info *bi = NULL;       /* must be initialized */
2064        s32 err = 0;
2065        int i;
2066
2067        bss_list = cfg_priv->bss_list;
2068        if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
2069                WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2070                       bss_list->version);
2071                return -EOPNOTSUPP;
2072        }
2073        WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2074        for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
2075                bi = next_bss(bss_list, bi);
2076                err = brcmf_inform_single_bss(cfg_priv, bi);
2077                if (err)
2078                        break;
2079        }
2080        return err;
2081}
2082
2083static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
2084                          struct net_device *ndev, const u8 *bssid)
2085{
2086        struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2087        struct ieee80211_channel *notify_channel;
2088        struct brcmf_bss_info *bi = NULL;
2089        struct ieee80211_supported_band *band;
2090        u8 *buf = NULL;
2091        s32 err = 0;
2092        u16 channel;
2093        u32 freq;
2094        u64 notify_timestamp;
2095        u16 notify_capability;
2096        u16 notify_interval;
2097        u8 *notify_ie;
2098        size_t notify_ielen;
2099        s32 notify_signal;
2100
2101        WL_TRACE("Enter\n");
2102
2103        buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2104        if (buf == NULL) {
2105                err = -ENOMEM;
2106                goto CleanUp;
2107        }
2108
2109        *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2110
2111        err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
2112        if (err) {
2113                WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2114                goto CleanUp;
2115        }
2116
2117        bi = (struct brcmf_bss_info *)(buf + 4);
2118
2119        channel = bi->ctl_ch ? bi->ctl_ch :
2120                                CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2121
2122        if (channel <= CH_MAX_2G_CHANNEL)
2123                band = wiphy->bands[IEEE80211_BAND_2GHZ];
2124        else
2125                band = wiphy->bands[IEEE80211_BAND_5GHZ];
2126
2127        freq = ieee80211_channel_to_frequency(channel, band->band);
2128        notify_channel = ieee80211_get_channel(wiphy, freq);
2129
2130        notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
2131        notify_capability = le16_to_cpu(bi->capability);
2132        notify_interval = le16_to_cpu(bi->beacon_period);
2133        notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2134        notify_ielen = le32_to_cpu(bi->ie_length);
2135        notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2136
2137        WL_CONN("channel: %d(%d)\n", channel, freq);
2138        WL_CONN("capability: %X\n", notify_capability);
2139        WL_CONN("beacon interval: %d\n", notify_interval);
2140        WL_CONN("signal: %d\n", notify_signal);
2141        WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
2142
2143        cfg80211_inform_bss(wiphy, notify_channel, bssid,
2144                notify_timestamp, notify_capability, notify_interval,
2145                notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2146
2147CleanUp:
2148
2149        kfree(buf);
2150
2151        WL_TRACE("Exit\n");
2152
2153        return err;
2154}
2155
2156static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
2157{
2158        return cfg_priv->conf->mode == WL_MODE_IBSS;
2159}
2160
2161/*
2162 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2163 * triples, returning a pointer to the substring whose first element
2164 * matches tag
2165 */
2166static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2167{
2168        struct brcmf_tlv *elt;
2169        int totlen;
2170
2171        elt = (struct brcmf_tlv *) buf;
2172        totlen = buflen;
2173
2174        /* find tagged parameter */
2175        while (totlen >= 2) {
2176                int len = elt->len;
2177
2178                /* validate remaining totlen */
2179                if ((elt->id == key) && (totlen >= (len + 2)))
2180                        return elt;
2181
2182                elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2));
2183                totlen -= (len + 2);
2184        }
2185
2186        return NULL;
2187}
2188
2189static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
2190{
2191        struct brcmf_bss_info *bi;
2192        struct brcmf_ssid *ssid;
2193        struct brcmf_tlv *tim;
2194        u16 beacon_interval;
2195        u8 dtim_period;
2196        size_t ie_len;
2197        u8 *ie;
2198        s32 err = 0;
2199
2200        WL_TRACE("Enter\n");
2201        if (brcmf_is_ibssmode(cfg_priv))
2202                return err;
2203
2204        ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
2205
2206        *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2207        err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
2208                        cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
2209        if (err) {
2210                WL_ERR("Could not get bss info %d\n", err);
2211                goto update_bss_info_out;
2212        }
2213
2214        bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
2215        err = brcmf_inform_single_bss(cfg_priv, bi);
2216        if (err)
2217                goto update_bss_info_out;
2218
2219        ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2220        ie_len = le32_to_cpu(bi->ie_length);
2221        beacon_interval = le16_to_cpu(bi->beacon_period);
2222
2223        tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
2224        if (tim)
2225                dtim_period = tim->data[1];
2226        else {
2227                /*
2228                * active scan was done so we could not get dtim
2229                * information out of probe response.
2230                * so we speficially query dtim information to dongle.
2231                */
2232                u32 var;
2233                err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
2234                                           "dtim_assoc", &var);
2235                if (err) {
2236                        WL_ERR("wl dtim_assoc failed (%d)\n", err);
2237                        goto update_bss_info_out;
2238                }
2239                dtim_period = (u8)var;
2240        }
2241
2242        brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
2243        brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
2244
2245update_bss_info_out:
2246        WL_TRACE("Exit");
2247        return err;
2248}
2249
2250static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2251{
2252        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2253        struct brcmf_ssid ssid;
2254
2255        if (cfg_priv->iscan_on) {
2256                iscan->state = WL_ISCAN_STATE_IDLE;
2257
2258                if (iscan->timer_on) {
2259                        del_timer_sync(&iscan->timer);
2260                        iscan->timer_on = 0;
2261                }
2262
2263                cancel_work_sync(&iscan->work);
2264
2265                /* Abort iscan running in FW */
2266                memset(&ssid, 0, sizeof(ssid));
2267                brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
2268        }
2269}
2270
2271static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2272                                        bool aborted)
2273{
2274        struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2275        struct net_device *ndev = cfg_to_ndev(cfg_priv);
2276
2277        if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2278                WL_ERR("Scan complete while device not scanning\n");
2279                return;
2280        }
2281        if (cfg_priv->scan_request) {
2282                WL_SCAN("ISCAN Completed scan: %s\n",
2283                                aborted ? "Aborted" : "Done");
2284                cfg80211_scan_done(cfg_priv->scan_request, aborted);
2285                brcmf_set_mpc(ndev, 1);
2286                cfg_priv->scan_request = NULL;
2287        }
2288        cfg_priv->iscan_kickstart = false;
2289}
2290
2291static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2292{
2293        if (iscan->state != WL_ISCAN_STATE_IDLE) {
2294                WL_SCAN("wake up iscan\n");
2295                schedule_work(&iscan->work);
2296                return 0;
2297        }
2298
2299        return -EIO;
2300}
2301
2302static s32
2303brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2304                     struct brcmf_scan_results **bss_list)
2305{
2306        struct brcmf_iscan_results list;
2307        struct brcmf_scan_results *results;
2308        struct brcmf_scan_results_le *results_le;
2309        struct brcmf_iscan_results *list_buf;
2310        s32 err = 0;
2311
2312        memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2313        list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2314        results = &list_buf->results;
2315        results_le = &list_buf->results_le;
2316        results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
2317        results->version = 0;
2318        results->count = 0;
2319
2320        memset(&list, 0, sizeof(list));
2321        list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
2322        err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
2323                                     BRCMF_ISCAN_RESULTS_FIXED_SIZE,
2324                                     iscan->scan_buf, WL_ISCAN_BUF_MAX);
2325        if (err) {
2326                WL_ERR("error (%d)\n", err);
2327                return err;
2328        }
2329        results->buflen = le32_to_cpu(results_le->buflen);
2330        results->version = le32_to_cpu(results_le->version);
2331        results->count = le32_to_cpu(results_le->count);
2332        WL_SCAN("results->count = %d\n", results_le->count);
2333        WL_SCAN("results->buflen = %d\n", results_le->buflen);
2334        *status = le32_to_cpu(list_buf->status_le);
2335        WL_SCAN("status = %d\n", *status);
2336        *bss_list = results;
2337
2338        return err;
2339}
2340
2341static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
2342{
2343        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2344        s32 err = 0;
2345
2346        iscan->state = WL_ISCAN_STATE_IDLE;
2347        brcmf_inform_bss(cfg_priv);
2348        brcmf_notify_iscan_complete(iscan, false);
2349
2350        return err;
2351}
2352
2353static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
2354{
2355        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2356        s32 err = 0;
2357
2358        /* Reschedule the timer */
2359        mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2360        iscan->timer_on = 1;
2361
2362        return err;
2363}
2364
2365static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
2366{
2367        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2368        s32 err = 0;
2369
2370        brcmf_inform_bss(cfg_priv);
2371        brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2372        /* Reschedule the timer */
2373        mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2374        iscan->timer_on = 1;
2375
2376        return err;
2377}
2378
2379static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
2380{
2381        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2382        s32 err = 0;
2383
2384        iscan->state = WL_ISCAN_STATE_IDLE;
2385        brcmf_notify_iscan_complete(iscan, true);
2386
2387        return err;
2388}
2389
2390static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2391{
2392        struct brcmf_cfg80211_iscan_ctrl *iscan =
2393                        container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2394                                     work);
2395        struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2396        struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2397        u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2398
2399        if (iscan->timer_on) {
2400                del_timer_sync(&iscan->timer);
2401                iscan->timer_on = 0;
2402        }
2403
2404        if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
2405                status = BRCMF_SCAN_RESULTS_ABORTED;
2406                WL_ERR("Abort iscan\n");
2407        }
2408
2409        el->handler[status](cfg_priv);
2410}
2411
2412static void brcmf_iscan_timer(unsigned long data)
2413{
2414        struct brcmf_cfg80211_iscan_ctrl *iscan =
2415                        (struct brcmf_cfg80211_iscan_ctrl *)data;
2416
2417        if (iscan) {
2418                iscan->timer_on = 0;
2419                WL_SCAN("timer expired\n");
2420                brcmf_wakeup_iscan(iscan);
2421        }
2422}
2423
2424static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2425{
2426        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2427
2428        if (cfg_priv->iscan_on) {
2429                iscan->state = WL_ISCAN_STATE_IDLE;
2430                INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2431        }
2432
2433        return 0;
2434}
2435
2436static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
2437{
2438        memset(el, 0, sizeof(*el));
2439        el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
2440        el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
2441        el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
2442        el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
2443        el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
2444}
2445
2446static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2447{
2448        struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2449        int err = 0;
2450
2451        if (cfg_priv->iscan_on) {
2452                iscan->ndev = cfg_to_ndev(cfg_priv);
2453                brcmf_init_iscan_eloop(&iscan->el);
2454                iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2455                init_timer(&iscan->timer);
2456                iscan->timer.data = (unsigned long) iscan;
2457                iscan->timer.function = brcmf_iscan_timer;
2458                err = brcmf_invoke_iscan(cfg_priv);
2459                if (!err)
2460                        iscan->data = cfg_priv;
2461        }
2462
2463        return err;
2464}
2465
2466static void brcmf_delay(u32 ms)
2467{
2468        if (ms < 1000 / HZ) {
2469                cond_resched();
2470                mdelay(ms);
2471        } else {
2472                msleep(ms);
2473        }
2474}
2475
2476static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2477{
2478        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2479
2480        /*
2481         * Check for WL_STATUS_READY before any function call which
2482         * could result is bus access. Don't block the resume for
2483         * any driver error conditions
2484         */
2485        WL_TRACE("Enter\n");
2486
2487        if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2488                brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
2489
2490        WL_TRACE("Exit\n");
2491        return 0;
2492}
2493
2494static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
2495                                  struct cfg80211_wowlan *wow)
2496{
2497        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2498        struct net_device *ndev = cfg_to_ndev(cfg_priv);
2499
2500        WL_TRACE("Enter\n");
2501
2502        /*
2503         * Check for WL_STATUS_READY before any function call which
2504         * could result is bus access. Don't block the suspend for
2505         * any driver error conditions
2506         */
2507
2508        /*
2509         * While going to suspend if associated with AP disassociate
2510         * from AP to save power while system is in suspended state
2511         */
2512        if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
2513             test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
2514             test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2515                WL_INFO("Disassociating from AP"
2516                        " while entering suspend state\n");
2517                brcmf_link_down(cfg_priv);
2518
2519                /*
2520                 * Make sure WPA_Supplicant receives all the event
2521                 * generated due to DISASSOC call to the fw to keep
2522                 * the state fw and WPA_Supplicant state consistent
2523                 */
2524                brcmf_delay(500);
2525        }
2526
2527        set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2528        if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2529                brcmf_term_iscan(cfg_priv);
2530
2531        if (cfg_priv->scan_request) {
2532                /* Indidate scan abort to cfg80211 layer */
2533                WL_INFO("Terminating scan in progress\n");
2534                cfg80211_scan_done(cfg_priv->scan_request, true);
2535                cfg_priv->scan_request = NULL;
2536        }
2537        clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
2538        clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2539
2540        /* Turn off watchdog timer */
2541        if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2542                WL_INFO("Enable MPC\n");
2543                brcmf_set_mpc(ndev, 1);
2544        }
2545
2546        WL_TRACE("Exit\n");
2547
2548        return 0;
2549}
2550
2551static __used s32
2552brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
2553{
2554        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
2555        u32 buflen;
2556
2557        buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
2558                               WL_DCMD_LEN_MAX);
2559        BUG_ON(!buflen);
2560
2561        return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
2562                               buflen);
2563}
2564
2565static s32
2566brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
2567                  s32 buf_len)
2568{
2569        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
2570        u32 len;
2571        s32 err = 0;
2572
2573        len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
2574                            WL_DCMD_LEN_MAX);
2575        BUG_ON(!len);
2576        err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
2577                              WL_DCMD_LEN_MAX);
2578        if (err) {
2579                WL_ERR("error (%d)\n", err);
2580                return err;
2581        }
2582        memcpy(buf, cfg_priv->dcmd_buf, buf_len);
2583
2584        return err;
2585}
2586
2587static __used s32
2588brcmf_update_pmklist(struct net_device *ndev,
2589                     struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
2590{
2591        int i, j;
2592        int pmkid_len;
2593
2594        pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
2595
2596        WL_CONN("No of elements %d\n", pmkid_len);
2597        for (i = 0; i < pmkid_len; i++) {
2598                WL_CONN("PMKID[%d]: %pM =\n", i,
2599                        &pmk_list->pmkids.pmkid[i].BSSID);
2600                for (j = 0; j < WLAN_PMKID_LEN; j++)
2601                        WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
2602        }
2603
2604        if (!err)
2605                brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
2606                                        sizeof(*pmk_list));
2607
2608        return err;
2609}
2610
2611static s32
2612brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2613                         struct cfg80211_pmksa *pmksa)
2614{
2615        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2616        struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
2617        s32 err = 0;
2618        int i;
2619        int pmkid_len;
2620
2621        WL_TRACE("Enter\n");
2622        if (!check_sys_up(wiphy))
2623                return -EIO;
2624
2625        pmkid_len = le32_to_cpu(pmkids->npmkid);
2626        for (i = 0; i < pmkid_len; i++)
2627                if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2628                        break;
2629        if (i < WL_NUM_PMKIDS_MAX) {
2630                memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2631                memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2632                if (i == pmkid_len) {
2633                        pmkid_len++;
2634                        pmkids->npmkid = cpu_to_le32(pmkid_len);
2635                }
2636        } else
2637                err = -EINVAL;
2638
2639        WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
2640                pmkids->pmkid[pmkid_len].BSSID);
2641        for (i = 0; i < WLAN_PMKID_LEN; i++)
2642                WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
2643
2644        err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2645
2646        WL_TRACE("Exit\n");
2647        return err;
2648}
2649
2650static s32
2651brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2652                      struct cfg80211_pmksa *pmksa)
2653{
2654        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2655        struct pmkid_list pmkid;
2656        s32 err = 0;
2657        int i, pmkid_len;
2658
2659        WL_TRACE("Enter\n");
2660        if (!check_sys_up(wiphy))
2661                return -EIO;
2662
2663        memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2664        memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2665
2666        WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2667               &pmkid.pmkid[0].BSSID);
2668        for (i = 0; i < WLAN_PMKID_LEN; i++)
2669                WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
2670
2671        pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
2672        for (i = 0; i < pmkid_len; i++)
2673                if (!memcmp
2674                    (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2675                     ETH_ALEN))
2676                        break;
2677
2678        if ((pmkid_len > 0)
2679            && (i < pmkid_len)) {
2680                memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
2681                       sizeof(struct pmkid));
2682                for (; i < (pmkid_len - 1); i++) {
2683                        memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2684                               &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
2685                               ETH_ALEN);
2686                        memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
2687                               &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
2688                               WLAN_PMKID_LEN);
2689                }
2690                cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
2691        } else
2692                err = -EINVAL;
2693
2694        err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2695
2696        WL_TRACE("Exit\n");
2697        return err;
2698
2699}
2700
2701static s32
2702brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
2703{
2704        struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2705        s32 err = 0;
2706
2707        WL_TRACE("Enter\n");
2708        if (!check_sys_up(wiphy))
2709                return -EIO;
2710
2711        memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
2712        err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2713
2714        WL_TRACE("Exit\n");
2715        return err;
2716
2717}
2718
2719static struct cfg80211_ops wl_cfg80211_ops = {
2720        .change_virtual_intf = brcmf_cfg80211_change_iface,
2721        .scan = brcmf_cfg80211_scan,
2722        .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
2723        .join_ibss = brcmf_cfg80211_join_ibss,
2724        .leave_ibss = brcmf_cfg80211_leave_ibss,
2725        .get_station = brcmf_cfg80211_get_station,
2726        .set_tx_power = brcmf_cfg80211_set_tx_power,
2727        .get_tx_power = brcmf_cfg80211_get_tx_power,
2728        .add_key = brcmf_cfg80211_add_key,
2729        .del_key = brcmf_cfg80211_del_key,
2730        .get_key = brcmf_cfg80211_get_key,
2731        .set_default_key = brcmf_cfg80211_config_default_key,
2732        .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
2733        .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
2734        .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
2735        .connect = brcmf_cfg80211_connect,
2736        .disconnect = brcmf_cfg80211_disconnect,
2737        .suspend = brcmf_cfg80211_suspend,
2738        .resume = brcmf_cfg80211_resume,
2739        .set_pmksa = brcmf_cfg80211_set_pmksa,
2740        .del_pmksa = brcmf_cfg80211_del_pmksa,
2741        .flush_pmksa = brcmf_cfg80211_flush_pmksa
2742};
2743
2744static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
2745{
2746        s32 err = 0;
2747
2748        switch (mode) {
2749        case WL_MODE_BSS:
2750                return NL80211_IFTYPE_STATION;
2751        case WL_MODE_IBSS:
2752                return NL80211_IFTYPE_ADHOC;
2753        default:
2754                return NL80211_IFTYPE_UNSPECIFIED;
2755        }
2756
2757        return err;
2758}
2759
2760static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
2761                                          struct device *ndev)
2762{
2763        struct wireless_dev *wdev;
2764        s32 err = 0;
2765
2766        wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2767        if (!wdev)
2768                return ERR_PTR(-ENOMEM);
2769
2770        wdev->wiphy =
2771            wiphy_new(&wl_cfg80211_ops,
2772                      sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
2773        if (!wdev->wiphy) {
2774                WL_ERR("Couldn not allocate wiphy device\n");
2775                err = -ENOMEM;
2776                goto wiphy_new_out;
2777        }
2778        set_wiphy_dev(wdev->wiphy, ndev);
2779        wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2780        wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2781        wdev->wiphy->interface_modes =
2782            BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2783        wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2784        wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;    /* Set
2785                                                * it as 11a by default.
2786                                                * This will be updated with
2787                                                * 11n phy tables in
2788                                                * "ifconfig up"
2789                                                * if phy has 11n capability
2790                                                */
2791        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2792        wdev->wiphy->cipher_suites = __wl_cipher_suites;
2793        wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2794        wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;      /* enable power
2795                                                                 * save mode
2796                                                                 * by default
2797                                                                 */
2798        err = wiphy_register(wdev->wiphy);
2799        if (err < 0) {
2800                WL_ERR("Couldn not register wiphy device (%d)\n", err);
2801                goto wiphy_register_out;
2802        }
2803        return wdev;
2804
2805wiphy_register_out:
2806        wiphy_free(wdev->wiphy);
2807
2808wiphy_new_out:
2809        kfree(wdev);
2810
2811        return ERR_PTR(err);
2812}
2813
2814static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
2815{
2816        struct wireless_dev *wdev = cfg_priv->wdev;
2817
2818        if (!wdev) {
2819                WL_ERR("wdev is invalid\n");
2820                return;
2821        }
2822        wiphy_unregister(wdev->wiphy);
2823        wiphy_free(wdev->wiphy);
2824        kfree(wdev);
2825        cfg_priv->wdev = NULL;
2826}
2827
2828static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
2829                            const struct brcmf_event_msg *e)
2830{
2831        u32 event = be32_to_cpu(e->event_type);
2832        u32 status = be32_to_cpu(e->status);
2833
2834        if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
2835                WL_CONN("Processing set ssid\n");
2836                cfg_priv->link_up = true;
2837                return true;
2838        }
2839
2840        return false;
2841}
2842
2843static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
2844                              const struct brcmf_event_msg *e)
2845{
2846        u32 event = be32_to_cpu(e->event_type);
2847        u16 flags = be16_to_cpu(e->flags);
2848
2849        if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
2850                WL_CONN("Processing link down\n");
2851                return true;
2852        }
2853        return false;
2854}
2855
2856static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
2857                               const struct brcmf_event_msg *e)
2858{
2859        u32 event = be32_to_cpu(e->event_type);
2860        u32 status = be32_to_cpu(e->status);
2861
2862        if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
2863                WL_CONN("Processing Link %s & no network found\n",
2864                                be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
2865                                "up" : "down");
2866                return true;
2867        }
2868
2869        if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
2870                WL_CONN("Processing connecting & no network found\n");
2871                return true;
2872        }
2873
2874        return false;
2875}
2876
2877static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2878{
2879        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2880
2881        kfree(conn_info->req_ie);
2882        conn_info->req_ie = NULL;
2883        conn_info->req_ie_len = 0;
2884        kfree(conn_info->resp_ie);
2885        conn_info->resp_ie = NULL;
2886        conn_info->resp_ie_len = 0;
2887}
2888
2889static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2890{
2891        struct net_device *ndev = cfg_to_ndev(cfg_priv);
2892        struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
2893        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2894        u32 req_len;
2895        u32 resp_len;
2896        s32 err = 0;
2897
2898        brcmf_clear_assoc_ies(cfg_priv);
2899
2900        err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
2901                                WL_ASSOC_INFO_MAX);
2902        if (err) {
2903                WL_ERR("could not get assoc info (%d)\n", err);
2904                return err;
2905        }
2906        assoc_info =
2907                (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
2908        req_len = le32_to_cpu(assoc_info->req_len);
2909        resp_len = le32_to_cpu(assoc_info->resp_len);
2910        if (req_len) {
2911                err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
2912                                           cfg_priv->extra_buf,
2913                                           WL_ASSOC_INFO_MAX);
2914                if (err) {
2915                        WL_ERR("could not get assoc req (%d)\n", err);
2916                        return err;
2917                }
2918                conn_info->req_ie_len = req_len;
2919                conn_info->req_ie =
2920                    kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
2921                            GFP_KERNEL);
2922        } else {
2923                conn_info->req_ie_len = 0;
2924                conn_info->req_ie = NULL;
2925        }
2926        if (resp_len) {
2927                err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
2928                                           cfg_priv->extra_buf,
2929                                           WL_ASSOC_INFO_MAX);
2930                if (err) {
2931                        WL_ERR("could not get assoc resp (%d)\n", err);
2932                        return err;
2933                }
2934                conn_info->resp_ie_len = resp_len;
2935                conn_info->resp_ie =
2936                    kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
2937                            GFP_KERNEL);
2938        } else {
2939                conn_info->resp_ie_len = 0;
2940                conn_info->resp_ie = NULL;
2941        }
2942        WL_CONN("req len (%d) resp len (%d)\n",
2943               conn_info->req_ie_len, conn_info->resp_ie_len);
2944
2945        return err;
2946}
2947
2948static s32
2949brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
2950                       struct net_device *ndev,
2951                       const struct brcmf_event_msg *e)
2952{
2953        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2954        struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2955        struct brcmf_channel_info_le channel_le;
2956        struct ieee80211_channel *notify_channel;
2957        struct ieee80211_supported_band *band;
2958        u32 freq;
2959        s32 err = 0;
2960        u32 target_channel;
2961
2962        WL_TRACE("Enter\n");
2963
2964        brcmf_get_assoc_ies(cfg_priv);
2965        brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
2966        brcmf_update_bss_info(cfg_priv);
2967
2968        brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
2969                        sizeof(channel_le));
2970
2971        target_channel = le32_to_cpu(channel_le.target_channel);
2972        WL_CONN("Roamed to channel %d\n", target_channel);
2973
2974        if (target_channel <= CH_MAX_2G_CHANNEL)
2975                band = wiphy->bands[IEEE80211_BAND_2GHZ];
2976        else
2977                band = wiphy->bands[IEEE80211_BAND_5GHZ];
2978
2979        freq = ieee80211_channel_to_frequency(target_channel, band->band);
2980        notify_channel = ieee80211_get_channel(wiphy, freq);
2981
2982        cfg80211_roamed(ndev, notify_channel,
2983                        (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
2984                        conn_info->req_ie, conn_info->req_ie_len,
2985                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2986        WL_CONN("Report roaming result\n");
2987
2988        set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2989        WL_TRACE("Exit\n");
2990        return err;
2991}
2992
2993static s32
2994brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
2995                       struct net_device *ndev, const struct brcmf_event_msg *e,
2996                       bool completed)
2997{
2998        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2999        s32 err = 0;
3000
3001        WL_TRACE("Enter\n");
3002
3003        if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
3004                if (completed) {
3005                        brcmf_get_assoc_ies(cfg_priv);
3006                        brcmf_update_prof(cfg_priv, NULL, &e->addr,
3007                                          WL_PROF_BSSID);
3008                        brcmf_update_bss_info(cfg_priv);
3009                }
3010                cfg80211_connect_result(ndev,
3011                                        (u8 *)brcmf_read_prof(cfg_priv,
3012                                                              WL_PROF_BSSID),
3013                                        conn_info->req_ie,
3014                                        conn_info->req_ie_len,
3015                                        conn_info->resp_ie,
3016                                        conn_info->resp_ie_len,
3017                                        completed ? WLAN_STATUS_SUCCESS :
3018                                                    WLAN_STATUS_AUTH_TIMEOUT,
3019                                        GFP_KERNEL);
3020                if (completed)
3021                        set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3022                WL_CONN("Report connect result - connection %s\n",
3023                                completed ? "succeeded" : "failed");
3024        }
3025        WL_TRACE("Exit\n");
3026        return err;
3027}
3028
3029static s32
3030brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
3031                            struct net_device *ndev,
3032                            const struct brcmf_event_msg *e, void *data)
3033{
3034        s32 err = 0;
3035
3036        if (brcmf_is_linkup(cfg_priv, e)) {
3037                WL_CONN("Linkup\n");
3038                if (brcmf_is_ibssmode(cfg_priv)) {
3039                        brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
3040                                WL_PROF_BSSID);
3041                        wl_inform_ibss(cfg_priv, ndev, e->addr);
3042                        cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
3043                        clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3044                        set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3045                } else
3046                        brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3047        } else if (brcmf_is_linkdown(cfg_priv, e)) {
3048                WL_CONN("Linkdown\n");
3049                if (brcmf_is_ibssmode(cfg_priv)) {
3050                        clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3051                        if (test_and_clear_bit(WL_STATUS_CONNECTED,
3052                                &cfg_priv->status))
3053                                brcmf_link_down(cfg_priv);
3054                } else {
3055                        brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3056                        if (test_and_clear_bit(WL_STATUS_CONNECTED,
3057                                &cfg_priv->status)) {
3058                                cfg80211_disconnected(ndev, 0, NULL, 0,
3059                                        GFP_KERNEL);
3060                                brcmf_link_down(cfg_priv);
3061                        }
3062                }
3063                brcmf_init_prof(cfg_priv->profile);
3064        } else if (brcmf_is_nonetwork(cfg_priv, e)) {
3065                if (brcmf_is_ibssmode(cfg_priv))
3066                        clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3067                else
3068                        brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3069        }
3070
3071        return err;
3072}
3073
3074static s32
3075brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
3076                            struct net_device *ndev,
3077                            const struct brcmf_event_msg *e, void *data)
3078{
3079        s32 err = 0;
3080        u32 event = be32_to_cpu(e->event_type);
3081        u32 status = be32_to_cpu(e->status);
3082
3083        if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
3084                if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
3085                        brcmf_bss_roaming_done(cfg_priv, ndev, e);
3086                else
3087                        brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3088        }
3089
3090        return err;
3091}
3092
3093static s32
3094brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
3095                        struct net_device *ndev,
3096                        const struct brcmf_event_msg *e, void *data)
3097{
3098        u16 flags = be16_to_cpu(e->flags);
3099        enum nl80211_key_type key_type;
3100
3101        if (flags & BRCMF_EVENT_MSG_GROUP)
3102                key_type = NL80211_KEYTYPE_GROUP;
3103        else
3104                key_type = NL80211_KEYTYPE_PAIRWISE;
3105
3106        cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
3107                                     NULL, GFP_KERNEL);
3108
3109        return 0;
3110}
3111
3112static s32
3113brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
3114                         struct net_device *ndev,
3115                         const struct brcmf_event_msg *e, void *data)
3116{
3117        struct brcmf_channel_info_le channel_inform_le;
3118        struct brcmf_scan_results_le *bss_list_le;
3119        u32 len = WL_SCAN_BUF_MAX;
3120        s32 err = 0;
3121        bool scan_abort = false;
3122        u32 scan_channel;
3123
3124        WL_TRACE("Enter\n");
3125
3126        if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
3127                WL_TRACE("Exit\n");
3128                return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
3129        }
3130
3131        if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3132                WL_ERR("Scan complete while device not scanning\n");
3133                scan_abort = true;
3134                err = -EINVAL;
3135                goto scan_done_out;
3136        }
3137
3138        err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
3139                              sizeof(channel_inform_le));
3140        if (err) {
3141                WL_ERR("scan busy (%d)\n", err);
3142                scan_abort = true;
3143                goto scan_done_out;
3144        }
3145        scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
3146        if (scan_channel)
3147                WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
3148        cfg_priv->bss_list = cfg_priv->scan_results;
3149        bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
3150
3151        memset(cfg_priv->scan_results, 0, len);
3152        bss_list_le->buflen = cpu_to_le32(len);
3153        err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
3154                              cfg_priv->scan_results, len);
3155        if (err) {
3156                WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3157                err = -EINVAL;
3158                scan_abort = true;
3159                goto scan_done_out;
3160        }
3161        cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
3162        cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
3163        cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
3164
3165        err = brcmf_inform_bss(cfg_priv);
3166        if (err) {
3167                scan_abort = true;
3168                goto scan_done_out;
3169        }
3170
3171scan_done_out:
3172        if (cfg_priv->scan_request) {
3173                WL_SCAN("calling cfg80211_scan_done\n");
3174                cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3175                brcmf_set_mpc(ndev, 1);
3176                cfg_priv->scan_request = NULL;
3177        }
3178
3179        WL_TRACE("Exit\n");
3180
3181        return err;
3182}
3183
3184static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3185{
3186        conf->mode = (u32)-1;
3187        conf->frag_threshold = (u32)-1;
3188        conf->rts_threshold = (u32)-1;
3189        conf->retry_short = (u32)-1;
3190        conf->retry_long = (u32)-1;
3191        conf->tx_power = -1;
3192}
3193
3194static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3195{
3196        memset(el, 0, sizeof(*el));
3197        el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3198        el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3199        el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3200        el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3201        el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3202}
3203
3204static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3205{
3206        kfree(cfg_priv->scan_results);
3207        cfg_priv->scan_results = NULL;
3208        kfree(cfg_priv->bss_info);
3209        cfg_priv->bss_info = NULL;
3210        kfree(cfg_priv->conf);
3211        cfg_priv->conf = NULL;
3212        kfree(cfg_priv->profile);
3213        cfg_priv->profile = NULL;
3214        kfree(cfg_priv->scan_req_int);
3215        cfg_priv->scan_req_int = NULL;
3216        kfree(cfg_priv->dcmd_buf);
3217        cfg_priv->dcmd_buf = NULL;
3218        kfree(cfg_priv->extra_buf);
3219        cfg_priv->extra_buf = NULL;
3220        kfree(cfg_priv->iscan);
3221        cfg_priv->iscan = NULL;
3222        kfree(cfg_priv->pmk_list);
3223        cfg_priv->pmk_list = NULL;
3224}
3225
3226static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3227{
3228        cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3229        if (!cfg_priv->scan_results)
3230                goto init_priv_mem_out;
3231        cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3232        if (!cfg_priv->conf)
3233                goto init_priv_mem_out;
3234        cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3235        if (!cfg_priv->profile)
3236                goto init_priv_mem_out;
3237        cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3238        if (!cfg_priv->bss_info)
3239                goto init_priv_mem_out;
3240        cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3241                                         GFP_KERNEL);
3242        if (!cfg_priv->scan_req_int)
3243                goto init_priv_mem_out;
3244        cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
3245        if (!cfg_priv->dcmd_buf)
3246                goto init_priv_mem_out;
3247        cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3248        if (!cfg_priv->extra_buf)
3249                goto init_priv_mem_out;
3250        cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3251        if (!cfg_priv->iscan)
3252                goto init_priv_mem_out;
3253        cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3254        if (!cfg_priv->pmk_list)
3255                goto init_priv_mem_out;
3256
3257        return 0;
3258
3259init_priv_mem_out:
3260        brcmf_deinit_priv_mem(cfg_priv);
3261
3262        return -ENOMEM;
3263}
3264
3265/*
3266* retrieve first queued event from head
3267*/
3268
3269static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3270        struct brcmf_cfg80211_priv *cfg_priv)
3271{
3272        struct brcmf_cfg80211_event_q *e = NULL;
3273
3274        spin_lock_irq(&cfg_priv->evt_q_lock);
3275        if (!list_empty(&cfg_priv->evt_q_list)) {
3276                e = list_first_entry(&cfg_priv->evt_q_list,
3277                                     struct brcmf_cfg80211_event_q, evt_q_list);
3278                list_del(&e->evt_q_list);
3279        }
3280        spin_unlock_irq(&cfg_priv->evt_q_lock);
3281
3282        return e;
3283}
3284
3285/*
3286** push event to tail of the queue
3287*/
3288
3289static s32
3290brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
3291                const struct brcmf_event_msg *msg)
3292{
3293        struct brcmf_cfg80211_event_q *e;
3294        s32 err = 0;
3295
3296        e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
3297        if (!e)
3298                return -ENOMEM;
3299
3300        e->etype = event;
3301        memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
3302
3303        spin_lock_irq(&cfg_priv->evt_q_lock);
3304        list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
3305        spin_unlock_irq(&cfg_priv->evt_q_lock);
3306
3307        return err;
3308}
3309
3310static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3311{
3312        kfree(e);
3313}
3314
3315static void brcmf_cfg80211_event_handler(struct work_struct *work)
3316{
3317        struct brcmf_cfg80211_priv *cfg_priv =
3318                        container_of(work, struct brcmf_cfg80211_priv,
3319                                     event_work);
3320        struct brcmf_cfg80211_event_q *e;
3321
3322        e = brcmf_deq_event(cfg_priv);
3323        if (unlikely(!e)) {
3324                WL_ERR("event queue empty...\n");
3325                return;
3326        }
3327
3328        do {
3329                WL_INFO("event type (%d)\n", e->etype);
3330                if (cfg_priv->el.handler[e->etype])
3331                        cfg_priv->el.handler[e->etype](cfg_priv,
3332                                                       cfg_to_ndev(cfg_priv),
3333                                                       &e->emsg, e->edata);
3334                else
3335                        WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3336                brcmf_put_event(e);
3337        } while ((e = brcmf_deq_event(cfg_priv)));
3338
3339}
3340
3341static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3342{
3343        spin_lock_init(&cfg_priv->evt_q_lock);
3344        INIT_LIST_HEAD(&cfg_priv->evt_q_list);
3345}
3346
3347static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3348{
3349        struct brcmf_cfg80211_event_q *e;
3350
3351        spin_lock_irq(&cfg_priv->evt_q_lock);
3352        while (!list_empty(&cfg_priv->evt_q_list)) {
3353                e = list_first_entry(&cfg_priv->evt_q_list,
3354                                     struct brcmf_cfg80211_event_q, evt_q_list);
3355                list_del(&e->evt_q_list);
3356                kfree(e);
3357        }
3358        spin_unlock_irq(&cfg_priv->evt_q_lock);
3359}
3360
3361static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3362{
3363        s32 err = 0;
3364
3365        cfg_priv->scan_request = NULL;
3366        cfg_priv->pwr_save = true;
3367        cfg_priv->iscan_on = true;      /* iscan on & off switch.
3368                                 we enable iscan per default */
3369        cfg_priv->roam_on = true;       /* roam on & off switch.
3370                                 we enable roam per default */
3371
3372        cfg_priv->iscan_kickstart = false;
3373        cfg_priv->active_scan = true;   /* we do active scan for
3374                                 specific scan per default */
3375        cfg_priv->dongle_up = false;    /* dongle is not up yet */
3376        brcmf_init_eq(cfg_priv);
3377        err = brcmf_init_priv_mem(cfg_priv);
3378        if (err)
3379                return err;
3380        INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
3381        brcmf_init_eloop_handler(&cfg_priv->el);
3382        mutex_init(&cfg_priv->usr_sync);
3383        err = brcmf_init_iscan(cfg_priv);
3384        if (err)
3385                return err;
3386        brcmf_init_conf(cfg_priv->conf);
3387        brcmf_init_prof(cfg_priv->profile);
3388        brcmf_link_down(cfg_priv);
3389
3390        return err;
3391}
3392
3393static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3394{
3395        cancel_work_sync(&cfg_priv->event_work);
3396        cfg_priv->dongle_up = false;    /* dongle down */
3397        brcmf_flush_eq(cfg_priv);
3398        brcmf_link_down(cfg_priv);
3399        brcmf_term_iscan(cfg_priv);
3400        brcmf_deinit_priv_mem(cfg_priv);
3401}
3402
3403struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
3404                                                 struct device *busdev,
3405                                                 void *data)
3406{
3407        struct wireless_dev *wdev;
3408        struct brcmf_cfg80211_priv *cfg_priv;
3409        struct brcmf_cfg80211_iface *ci;
3410        struct brcmf_cfg80211_dev *cfg_dev;
3411        s32 err = 0;
3412
3413        if (!ndev) {
3414                WL_ERR("ndev is invalid\n");
3415                return NULL;
3416        }
3417        cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3418        if (!cfg_dev)
3419                return NULL;
3420
3421        wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
3422        if (IS_ERR(wdev)) {
3423                kfree(cfg_dev);
3424                return NULL;
3425        }
3426
3427        wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3428        cfg_priv = wdev_to_cfg(wdev);
3429        cfg_priv->wdev = wdev;
3430        cfg_priv->pub = data;
3431        ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3432        ci->cfg_priv = cfg_priv;
3433        ndev->ieee80211_ptr = wdev;
3434        SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3435        wdev->netdev = ndev;
3436        err = wl_init_priv(cfg_priv);
3437        if (err) {
3438                WL_ERR("Failed to init iwm_priv (%d)\n", err);
3439                goto cfg80211_attach_out;
3440        }
3441        brcmf_set_drvdata(cfg_dev, ci);
3442
3443        return cfg_dev;
3444
3445cfg80211_attach_out:
3446        brcmf_free_wdev(cfg_priv);
3447        kfree(cfg_dev);
3448        return NULL;
3449}
3450
3451void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
3452{
3453        struct brcmf_cfg80211_priv *cfg_priv;
3454
3455        cfg_priv = brcmf_priv_get(cfg_dev);
3456
3457        wl_deinit_priv(cfg_priv);
3458        brcmf_free_wdev(cfg_priv);
3459        brcmf_set_drvdata(cfg_dev, NULL);
3460        kfree(cfg_dev);
3461}
3462
3463void
3464brcmf_cfg80211_event(struct net_device *ndev,
3465                  const struct brcmf_event_msg *e, void *data)
3466{
3467        u32 event_type = be32_to_cpu(e->event_type);
3468        struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3469
3470        if (!brcmf_enq_event(cfg_priv, event_type, e))
3471                schedule_work(&cfg_priv->event_work);
3472}
3473
3474static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
3475{
3476        s32 infra = 0;
3477        s32 err = 0;
3478
3479        switch (iftype) {
3480        case NL80211_IFTYPE_MONITOR:
3481        case NL80211_IFTYPE_WDS:
3482                WL_ERR("type (%d) : currently we do not support this mode\n",
3483                       iftype);
3484                err = -EINVAL;
3485                return err;
3486        case NL80211_IFTYPE_ADHOC:
3487                infra = 0;
3488                break;
3489        case NL80211_IFTYPE_STATION:
3490                infra = 1;
3491                break;
3492        default:
3493                err = -EINVAL;
3494                WL_ERR("invalid type (%d)\n", iftype);
3495                return err;
3496        }
3497        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
3498        if (err) {
3499                WL_ERR("WLC_SET_INFRA error (%d)\n", err);
3500                return err;
3501        }
3502
3503        return 0;
3504}
3505
3506static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
3507{
3508        /* Room for "event_msgs" + '\0' + bitvec */
3509        s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
3510        s8 eventmask[BRCMF_EVENTING_MASK_LEN];
3511        s32 err = 0;
3512
3513        WL_TRACE("Enter\n");
3514
3515        /* Setup event_msgs */
3516        brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
3517                        iovbuf, sizeof(iovbuf));
3518        err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
3519        if (err) {
3520                WL_ERR("Get event_msgs error (%d)\n", err);
3521                goto dongle_eventmsg_out;
3522        }
3523        memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
3524
3525        setbit(eventmask, BRCMF_E_SET_SSID);
3526        setbit(eventmask, BRCMF_E_ROAM);
3527        setbit(eventmask, BRCMF_E_PRUNE);
3528        setbit(eventmask, BRCMF_E_AUTH);
3529        setbit(eventmask, BRCMF_E_REASSOC);
3530        setbit(eventmask, BRCMF_E_REASSOC_IND);
3531        setbit(eventmask, BRCMF_E_DEAUTH_IND);
3532        setbit(eventmask, BRCMF_E_DISASSOC_IND);
3533        setbit(eventmask, BRCMF_E_DISASSOC);
3534        setbit(eventmask, BRCMF_E_JOIN);
3535        setbit(eventmask, BRCMF_E_ASSOC_IND);
3536        setbit(eventmask, BRCMF_E_PSK_SUP);
3537        setbit(eventmask, BRCMF_E_LINK);
3538        setbit(eventmask, BRCMF_E_NDIS_LINK);
3539        setbit(eventmask, BRCMF_E_MIC_ERROR);
3540        setbit(eventmask, BRCMF_E_PMKID_CACHE);
3541        setbit(eventmask, BRCMF_E_TXFAIL);
3542        setbit(eventmask, BRCMF_E_JOIN_START);
3543        setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
3544
3545        brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
3546                        iovbuf, sizeof(iovbuf));
3547        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3548        if (err) {
3549                WL_ERR("Set event_msgs error (%d)\n", err);
3550                goto dongle_eventmsg_out;
3551        }
3552
3553dongle_eventmsg_out:
3554        WL_TRACE("Exit\n");
3555        return err;
3556}
3557
3558static s32
3559brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
3560{
3561        s8 iovbuf[32];
3562        s32 err = 0;
3563        __le32 roamtrigger[2];
3564        __le32 roam_delta[2];
3565        __le32 bcn_to_le;
3566        __le32 roamvar_le;
3567
3568        /*
3569         * Setup timeout if Beacons are lost and roam is
3570         * off to report link down
3571         */
3572        if (roamvar) {
3573                bcn_to_le = cpu_to_le32(bcn_timeout);
3574                brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
3575                        sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
3576                err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
3577                                   iovbuf, sizeof(iovbuf));
3578                if (err) {
3579                        WL_ERR("bcn_timeout error (%d)\n", err);
3580                        goto dongle_rom_out;
3581                }
3582        }
3583
3584        /*
3585         * Enable/Disable built-in roaming to allow supplicant
3586         * to take care of roaming
3587         */
3588        WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
3589        roamvar_le = cpu_to_le32(roamvar);
3590        brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
3591                                sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
3592        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3593        if (err) {
3594                WL_ERR("roam_off error (%d)\n", err);
3595                goto dongle_rom_out;
3596        }
3597
3598        roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
3599        roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
3600        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
3601                        (void *)roamtrigger, sizeof(roamtrigger));
3602        if (err) {
3603                WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
3604                goto dongle_rom_out;
3605        }
3606
3607        roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
3608        roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
3609        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
3610                                (void *)roam_delta, sizeof(roam_delta));
3611        if (err) {
3612                WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
3613                goto dongle_rom_out;
3614        }
3615
3616dongle_rom_out:
3617        return err;
3618}
3619
3620static s32
3621brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
3622                      s32 scan_unassoc_time, s32 scan_passive_time)
3623{
3624        s32 err = 0;
3625        __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
3626        __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
3627        __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
3628
3629        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
3630                           &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
3631        if (err) {
3632                if (err == -EOPNOTSUPP)
3633                        WL_INFO("Scan assoc time is not supported\n");
3634                else
3635                        WL_ERR("Scan assoc time error (%d)\n", err);
3636                goto dongle_scantime_out;
3637        }
3638        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
3639                           &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
3640        if (err) {
3641                if (err == -EOPNOTSUPP)
3642                        WL_INFO("Scan unassoc time is not supported\n");
3643                else
3644                        WL_ERR("Scan unassoc time error (%d)\n", err);
3645                goto dongle_scantime_out;
3646        }
3647
3648        err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
3649                           &scan_passive_tm_le, sizeof(scan_passive_tm_le));
3650        if (err) {
3651                if (err == -EOPNOTSUPP)
3652                        WL_INFO("Scan passive time is not supported\n");
3653                else
3654                        WL_ERR("Scan passive time error (%d)\n", err);
3655                goto dongle_scantime_out;
3656        }
3657
3658dongle_scantime_out:
3659        return err;
3660}
3661
3662static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
3663{
3664        struct wiphy *wiphy;
3665        s32 phy_list;
3666        s8 phy;
3667        s32 err = 0;
3668
3669        err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
3670                              &phy_list, sizeof(phy_list));
3671        if (err) {
3672                WL_ERR("error (%d)\n", err);
3673                return err;
3674        }
3675
3676        phy = ((char *)&phy_list)[1];
3677        WL_INFO("%c phy\n", phy);
3678        if (phy == 'n' || phy == 'a') {
3679                wiphy = cfg_to_wiphy(cfg_priv);
3680                wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3681        }
3682
3683        return err;
3684}
3685
3686static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
3687{
3688        return wl_update_wiphybands(cfg_priv);
3689}
3690
3691static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
3692{
3693        struct net_device *ndev;
3694        struct wireless_dev *wdev;
3695        s32 power_mode;
3696        s32 err = 0;
3697
3698        if (cfg_priv->dongle_up)
3699                return err;
3700
3701        ndev = cfg_to_ndev(cfg_priv);
3702        wdev = ndev->ieee80211_ptr;
3703
3704        brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
3705                        WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
3706
3707        err = brcmf_dongle_eventmsg(ndev);
3708        if (err)
3709                goto default_conf_out;
3710
3711        power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
3712        err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
3713        if (err)
3714                goto default_conf_out;
3715        WL_INFO("power save set to %s\n",
3716                (power_mode ? "enabled" : "disabled"));
3717
3718        err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
3719                                WL_BEACON_TIMEOUT);
3720        if (err)
3721                goto default_conf_out;
3722        err = brcmf_dongle_mode(ndev, wdev->iftype);
3723        if (err && err != -EINPROGRESS)
3724                goto default_conf_out;
3725        err = brcmf_dongle_probecap(cfg_priv);
3726        if (err)
3727                goto default_conf_out;
3728
3729        /* -EINPROGRESS: Call commit handler */
3730
3731default_conf_out:
3732
3733        cfg_priv->dongle_up = true;
3734
3735        return err;
3736
3737}
3738
3739static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
3740{
3741        char buf[10+IFNAMSIZ];
3742        struct dentry *fd;
3743        s32 err = 0;
3744
3745        sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
3746        cfg_priv->debugfsdir = debugfs_create_dir(buf,
3747                                        cfg_to_wiphy(cfg_priv)->debugfsdir);
3748
3749        fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
3750                (u16 *)&cfg_priv->profile->beacon_interval);
3751        if (!fd) {
3752                err = -ENOMEM;
3753                goto err_out;
3754        }
3755
3756        fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
3757                (u8 *)&cfg_priv->profile->dtim_period);
3758        if (!fd) {
3759                err = -ENOMEM;
3760                goto err_out;
3761        }
3762
3763err_out:
3764        return err;
3765}
3766
3767static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
3768{
3769        debugfs_remove_recursive(cfg_priv->debugfsdir);
3770        cfg_priv->debugfsdir = NULL;
3771}
3772
3773static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
3774{
3775        s32 err = 0;
3776
3777        set_bit(WL_STATUS_READY, &cfg_priv->status);
3778
3779        brcmf_debugfs_add_netdev_params(cfg_priv);
3780
3781        err = brcmf_config_dongle(cfg_priv);
3782        if (err)
3783                return err;
3784
3785        brcmf_invoke_iscan(cfg_priv);
3786
3787        return err;
3788}
3789
3790static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
3791{
3792        /*
3793         * While going down, if associated with AP disassociate
3794         * from AP to save power
3795         */
3796        if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3797             test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3798             test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3799                WL_INFO("Disassociating from AP");
3800                brcmf_link_down(cfg_priv);
3801
3802                /* Make sure WPA_Supplicant receives all the event
3803                   generated due to DISASSOC call to the fw to keep
3804                   the state fw and WPA_Supplicant state consistent
3805                 */
3806                brcmf_delay(500);
3807        }
3808
3809        set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3810        brcmf_term_iscan(cfg_priv);
3811        if (cfg_priv->scan_request) {
3812                cfg80211_scan_done(cfg_priv->scan_request, true);
3813                /* May need to perform this to cover rmmod */
3814                /* wl_set_mpc(cfg_to_ndev(wl), 1); */
3815                cfg_priv->scan_request = NULL;
3816        }
3817        clear_bit(WL_STATUS_READY, &cfg_priv->status);
3818        clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3819        clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3820
3821        brcmf_debugfs_remove_netdev(cfg_priv);
3822
3823        return 0;
3824}
3825
3826s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
3827{
3828        struct brcmf_cfg80211_priv *cfg_priv;
3829        s32 err = 0;
3830
3831        cfg_priv = brcmf_priv_get(cfg_dev);
3832        mutex_lock(&cfg_priv->usr_sync);
3833        err = __brcmf_cfg80211_up(cfg_priv);
3834        mutex_unlock(&cfg_priv->usr_sync);
3835
3836        return err;
3837}
3838
3839s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
3840{
3841        struct brcmf_cfg80211_priv *cfg_priv;
3842        s32 err = 0;
3843
3844        cfg_priv = brcmf_priv_get(cfg_dev);
3845        mutex_lock(&cfg_priv->usr_sync);
3846        err = __brcmf_cfg80211_down(cfg_priv);
3847        mutex_unlock(&cfg_priv->usr_sync);
3848
3849        return err;
3850}
3851
3852static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
3853                               u8 t, u8 l, u8 *v)
3854{
3855        struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
3856        s32 err = 0;
3857
3858        if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
3859                WL_ERR("ei crosses buffer boundary\n");
3860                return -ENOSPC;
3861        }
3862        ie->buf[ie->offset] = t;
3863        ie->buf[ie->offset + 1] = l;
3864        memcpy(&ie->buf[ie->offset + 2], v, l);
3865        ie->offset += l + 2;
3866
3867        return err;
3868}
3869
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.