linux/drivers/net/wireless/ath/ath6kl/cfg80211.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004-2011 Atheros Communications Inc.
   3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 */
  17
  18#include <linux/moduleparam.h>
  19#include <linux/inetdevice.h>
  20#include <linux/export.h>
  21
  22#include "core.h"
  23#include "cfg80211.h"
  24#include "debug.h"
  25#include "hif-ops.h"
  26#include "testmode.h"
  27
  28#define RATETAB_ENT(_rate, _rateid, _flags) {   \
  29        .bitrate    = (_rate),                  \
  30        .flags      = (_flags),                 \
  31        .hw_value   = (_rateid),                \
  32}
  33
  34#define CHAN2G(_channel, _freq, _flags) {   \
  35        .band           = IEEE80211_BAND_2GHZ,  \
  36        .hw_value       = (_channel),           \
  37        .center_freq    = (_freq),              \
  38        .flags          = (_flags),             \
  39        .max_antenna_gain   = 0,                \
  40        .max_power      = 30,                   \
  41}
  42
  43#define CHAN5G(_channel, _flags) {                  \
  44        .band           = IEEE80211_BAND_5GHZ,      \
  45        .hw_value       = (_channel),               \
  46        .center_freq    = 5000 + (5 * (_channel)),  \
  47        .flags          = (_flags),                 \
  48        .max_antenna_gain   = 0,                    \
  49        .max_power      = 30,                       \
  50}
  51
  52static struct ieee80211_rate ath6kl_rates[] = {
  53        RATETAB_ENT(10, 0x1, 0),
  54        RATETAB_ENT(20, 0x2, 0),
  55        RATETAB_ENT(55, 0x4, 0),
  56        RATETAB_ENT(110, 0x8, 0),
  57        RATETAB_ENT(60, 0x10, 0),
  58        RATETAB_ENT(90, 0x20, 0),
  59        RATETAB_ENT(120, 0x40, 0),
  60        RATETAB_ENT(180, 0x80, 0),
  61        RATETAB_ENT(240, 0x100, 0),
  62        RATETAB_ENT(360, 0x200, 0),
  63        RATETAB_ENT(480, 0x400, 0),
  64        RATETAB_ENT(540, 0x800, 0),
  65};
  66
  67#define ath6kl_a_rates     (ath6kl_rates + 4)
  68#define ath6kl_a_rates_size    8
  69#define ath6kl_g_rates     (ath6kl_rates + 0)
  70#define ath6kl_g_rates_size    12
  71
  72#define ath6kl_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
  73                        IEEE80211_HT_CAP_SGI_20          | \
  74                        IEEE80211_HT_CAP_SGI_40)
  75
  76static struct ieee80211_channel ath6kl_2ghz_channels[] = {
  77        CHAN2G(1, 2412, 0),
  78        CHAN2G(2, 2417, 0),
  79        CHAN2G(3, 2422, 0),
  80        CHAN2G(4, 2427, 0),
  81        CHAN2G(5, 2432, 0),
  82        CHAN2G(6, 2437, 0),
  83        CHAN2G(7, 2442, 0),
  84        CHAN2G(8, 2447, 0),
  85        CHAN2G(9, 2452, 0),
  86        CHAN2G(10, 2457, 0),
  87        CHAN2G(11, 2462, 0),
  88        CHAN2G(12, 2467, 0),
  89        CHAN2G(13, 2472, 0),
  90        CHAN2G(14, 2484, 0),
  91};
  92
  93static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
  94        CHAN5G(34, 0), CHAN5G(36, 0),
  95        CHAN5G(38, 0), CHAN5G(40, 0),
  96        CHAN5G(42, 0), CHAN5G(44, 0),
  97        CHAN5G(46, 0), CHAN5G(48, 0),
  98        CHAN5G(52, 0), CHAN5G(56, 0),
  99        CHAN5G(60, 0), CHAN5G(64, 0),
 100        CHAN5G(100, 0), CHAN5G(104, 0),
 101        CHAN5G(108, 0), CHAN5G(112, 0),
 102        CHAN5G(116, 0), CHAN5G(120, 0),
 103        CHAN5G(124, 0), CHAN5G(128, 0),
 104        CHAN5G(132, 0), CHAN5G(136, 0),
 105        CHAN5G(140, 0), CHAN5G(149, 0),
 106        CHAN5G(153, 0), CHAN5G(157, 0),
 107        CHAN5G(161, 0), CHAN5G(165, 0),
 108        CHAN5G(184, 0), CHAN5G(188, 0),
 109        CHAN5G(192, 0), CHAN5G(196, 0),
 110        CHAN5G(200, 0), CHAN5G(204, 0),
 111        CHAN5G(208, 0), CHAN5G(212, 0),
 112        CHAN5G(216, 0),
 113};
 114
 115static struct ieee80211_supported_band ath6kl_band_2ghz = {
 116        .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels),
 117        .channels = ath6kl_2ghz_channels,
 118        .n_bitrates = ath6kl_g_rates_size,
 119        .bitrates = ath6kl_g_rates,
 120        .ht_cap.cap = ath6kl_g_htcap,
 121        .ht_cap.ht_supported = true,
 122};
 123
 124static struct ieee80211_supported_band ath6kl_band_5ghz = {
 125        .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels),
 126        .channels = ath6kl_5ghz_a_channels,
 127        .n_bitrates = ath6kl_a_rates_size,
 128        .bitrates = ath6kl_a_rates,
 129        .ht_cap.cap = ath6kl_g_htcap,
 130        .ht_cap.ht_supported = true,
 131};
 132
 133#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
 134
 135/* returns true if scheduled scan was stopped */
 136static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
 137{
 138        struct ath6kl *ar = vif->ar;
 139
 140        if (ar->state != ATH6KL_STATE_SCHED_SCAN)
 141                return false;
 142
 143        del_timer_sync(&vif->sched_scan_timer);
 144
 145        ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
 146                                           ATH6KL_HOST_MODE_AWAKE);
 147
 148        ar->state = ATH6KL_STATE_ON;
 149
 150        return true;
 151}
 152
 153static void ath6kl_cfg80211_sscan_disable(struct ath6kl_vif *vif)
 154{
 155        struct ath6kl *ar = vif->ar;
 156        bool stopped;
 157
 158        stopped = __ath6kl_cfg80211_sscan_stop(vif);
 159
 160        if (!stopped)
 161                return;
 162
 163        cfg80211_sched_scan_stopped(ar->wiphy);
 164}
 165
 166static int ath6kl_set_wpa_version(struct ath6kl_vif *vif,
 167                                  enum nl80211_wpa_versions wpa_version)
 168{
 169        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
 170
 171        if (!wpa_version) {
 172                vif->auth_mode = NONE_AUTH;
 173        } else if (wpa_version & NL80211_WPA_VERSION_2) {
 174                vif->auth_mode = WPA2_AUTH;
 175        } else if (wpa_version & NL80211_WPA_VERSION_1) {
 176                vif->auth_mode = WPA_AUTH;
 177        } else {
 178                ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
 179                return -ENOTSUPP;
 180        }
 181
 182        return 0;
 183}
 184
 185static int ath6kl_set_auth_type(struct ath6kl_vif *vif,
 186                                enum nl80211_auth_type auth_type)
 187{
 188        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
 189
 190        switch (auth_type) {
 191        case NL80211_AUTHTYPE_OPEN_SYSTEM:
 192                vif->dot11_auth_mode = OPEN_AUTH;
 193                break;
 194        case NL80211_AUTHTYPE_SHARED_KEY:
 195                vif->dot11_auth_mode = SHARED_AUTH;
 196                break;
 197        case NL80211_AUTHTYPE_NETWORK_EAP:
 198                vif->dot11_auth_mode = LEAP_AUTH;
 199                break;
 200
 201        case NL80211_AUTHTYPE_AUTOMATIC:
 202                vif->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
 203                break;
 204
 205        default:
 206                ath6kl_err("%s: 0x%x not supported\n", __func__, auth_type);
 207                return -ENOTSUPP;
 208        }
 209
 210        return 0;
 211}
 212
 213static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
 214{
 215        u8 *ar_cipher = ucast ? &vif->prwise_crypto : &vif->grp_crypto;
 216        u8 *ar_cipher_len = ucast ? &vif->prwise_crypto_len :
 217                &vif->grp_crypto_len;
 218
 219        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
 220                   __func__, cipher, ucast);
 221
 222        switch (cipher) {
 223        case 0:
 224                /* our own hack to use value 0 as no crypto used */
 225                *ar_cipher = NONE_CRYPT;
 226                *ar_cipher_len = 0;
 227                break;
 228        case WLAN_CIPHER_SUITE_WEP40:
 229                *ar_cipher = WEP_CRYPT;
 230                *ar_cipher_len = 5;
 231                break;
 232        case WLAN_CIPHER_SUITE_WEP104:
 233                *ar_cipher = WEP_CRYPT;
 234                *ar_cipher_len = 13;
 235                break;
 236        case WLAN_CIPHER_SUITE_TKIP:
 237                *ar_cipher = TKIP_CRYPT;
 238                *ar_cipher_len = 0;
 239                break;
 240        case WLAN_CIPHER_SUITE_CCMP:
 241                *ar_cipher = AES_CRYPT;
 242                *ar_cipher_len = 0;
 243                break;
 244        case WLAN_CIPHER_SUITE_SMS4:
 245                *ar_cipher = WAPI_CRYPT;
 246                *ar_cipher_len = 0;
 247                break;
 248        default:
 249                ath6kl_err("cipher 0x%x not supported\n", cipher);
 250                return -ENOTSUPP;
 251        }
 252
 253        return 0;
 254}
 255
 256static void ath6kl_set_key_mgmt(struct ath6kl_vif *vif, u32 key_mgmt)
 257{
 258        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
 259
 260        if (key_mgmt == WLAN_AKM_SUITE_PSK) {
 261                if (vif->auth_mode == WPA_AUTH)
 262                        vif->auth_mode = WPA_PSK_AUTH;
 263                else if (vif->auth_mode == WPA2_AUTH)
 264                        vif->auth_mode = WPA2_PSK_AUTH;
 265        } else if (key_mgmt == 0x00409600) {
 266                if (vif->auth_mode == WPA_AUTH)
 267                        vif->auth_mode = WPA_AUTH_CCKM;
 268                else if (vif->auth_mode == WPA2_AUTH)
 269                        vif->auth_mode = WPA2_AUTH_CCKM;
 270        } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
 271                vif->auth_mode = NONE_AUTH;
 272        }
 273}
 274
 275static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
 276{
 277        struct ath6kl *ar = vif->ar;
 278
 279        if (!test_bit(WMI_READY, &ar->flag)) {
 280                ath6kl_err("wmi is not ready\n");
 281                return false;
 282        }
 283
 284        if (!test_bit(WLAN_ENABLED, &vif->flags)) {
 285                ath6kl_err("wlan disabled\n");
 286                return false;
 287        }
 288
 289        return true;
 290}
 291
 292static bool ath6kl_is_wpa_ie(const u8 *pos)
 293{
 294        return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
 295                pos[2] == 0x00 && pos[3] == 0x50 &&
 296                pos[4] == 0xf2 && pos[5] == 0x01;
 297}
 298
 299static bool ath6kl_is_rsn_ie(const u8 *pos)
 300{
 301        return pos[0] == WLAN_EID_RSN;
 302}
 303
 304static bool ath6kl_is_wps_ie(const u8 *pos)
 305{
 306        return (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
 307                pos[1] >= 4 &&
 308                pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2 &&
 309                pos[5] == 0x04);
 310}
 311
 312static int ath6kl_set_assoc_req_ies(struct ath6kl_vif *vif, const u8 *ies,
 313                                    size_t ies_len)
 314{
 315        struct ath6kl *ar = vif->ar;
 316        const u8 *pos;
 317        u8 *buf = NULL;
 318        size_t len = 0;
 319        int ret;
 320
 321        /*
 322         * Clear previously set flag
 323         */
 324
 325        ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
 326
 327        /*
 328         * Filter out RSN/WPA IE(s)
 329         */
 330
 331        if (ies && ies_len) {
 332                buf = kmalloc(ies_len, GFP_KERNEL);
 333                if (buf == NULL)
 334                        return -ENOMEM;
 335                pos = ies;
 336
 337                while (pos + 1 < ies + ies_len) {
 338                        if (pos + 2 + pos[1] > ies + ies_len)
 339                                break;
 340                        if (!(ath6kl_is_wpa_ie(pos) || ath6kl_is_rsn_ie(pos))) {
 341                                memcpy(buf + len, pos, 2 + pos[1]);
 342                                len += 2 + pos[1];
 343                        }
 344
 345                        if (ath6kl_is_wps_ie(pos))
 346                                ar->connect_ctrl_flags |= CONNECT_WPS_FLAG;
 347
 348                        pos += 2 + pos[1];
 349                }
 350        }
 351
 352        ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
 353                                       WMI_FRAME_ASSOC_REQ, buf, len);
 354        kfree(buf);
 355        return ret;
 356}
 357
 358static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
 359{
 360        switch (type) {
 361        case NL80211_IFTYPE_STATION:
 362                *nw_type = INFRA_NETWORK;
 363                break;
 364        case NL80211_IFTYPE_ADHOC:
 365                *nw_type = ADHOC_NETWORK;
 366                break;
 367        case NL80211_IFTYPE_AP:
 368                *nw_type = AP_NETWORK;
 369                break;
 370        case NL80211_IFTYPE_P2P_CLIENT:
 371                *nw_type = INFRA_NETWORK;
 372                break;
 373        case NL80211_IFTYPE_P2P_GO:
 374                *nw_type = AP_NETWORK;
 375                break;
 376        default:
 377                ath6kl_err("invalid interface type %u\n", type);
 378                return -ENOTSUPP;
 379        }
 380
 381        return 0;
 382}
 383
 384static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
 385                                   u8 *if_idx, u8 *nw_type)
 386{
 387        int i;
 388
 389        if (ath6kl_nliftype_to_drv_iftype(type, nw_type))
 390                return false;
 391
 392        if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
 393                                   ar->num_vif))
 394                return false;
 395
 396        if (type == NL80211_IFTYPE_STATION ||
 397            type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
 398                for (i = 0; i < ar->vif_max; i++) {
 399                        if ((ar->avail_idx_map >> i) & BIT(0)) {
 400                                *if_idx = i;
 401                                return true;
 402                        }
 403                }
 404        }
 405
 406        if (type == NL80211_IFTYPE_P2P_CLIENT ||
 407            type == NL80211_IFTYPE_P2P_GO) {
 408                for (i = ar->max_norm_iface; i < ar->vif_max; i++) {
 409                        if ((ar->avail_idx_map >> i) & BIT(0)) {
 410                                *if_idx = i;
 411                                return true;
 412                        }
 413                }
 414        }
 415
 416        return false;
 417}
 418
 419static bool ath6kl_is_tx_pending(struct ath6kl *ar)
 420{
 421        return ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0;
 422}
 423
 424
 425static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 426                                   struct cfg80211_connect_params *sme)
 427{
 428        struct ath6kl *ar = ath6kl_priv(dev);
 429        struct ath6kl_vif *vif = netdev_priv(dev);
 430        int status;
 431        u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
 432        u16 interval;
 433
 434        ath6kl_cfg80211_sscan_disable(vif);
 435
 436        vif->sme_state = SME_CONNECTING;
 437
 438        if (!ath6kl_cfg80211_ready(vif))
 439                return -EIO;
 440
 441        if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
 442                ath6kl_err("destroy in progress\n");
 443                return -EBUSY;
 444        }
 445
 446        if (test_bit(SKIP_SCAN, &ar->flag) &&
 447            ((sme->channel && sme->channel->center_freq == 0) ||
 448             (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
 449                ath6kl_err("SkipScan: channel or bssid invalid\n");
 450                return -EINVAL;
 451        }
 452
 453        if (down_interruptible(&ar->sem)) {
 454                ath6kl_err("busy, couldn't get access\n");
 455                return -ERESTARTSYS;
 456        }
 457
 458        if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
 459                ath6kl_err("busy, destroy in progress\n");
 460                up(&ar->sem);
 461                return -EBUSY;
 462        }
 463
 464        if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
 465                /*
 466                 * sleep until the command queue drains
 467                 */
 468                wait_event_interruptible_timeout(ar->event_wq,
 469                                                 ath6kl_is_tx_pending(ar),
 470                                                 WMI_TIMEOUT);
 471                if (signal_pending(current)) {
 472                        ath6kl_err("cmd queue drain timeout\n");
 473                        up(&ar->sem);
 474                        return -EINTR;
 475                }
 476        }
 477
 478        status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len);
 479        if (status) {
 480                up(&ar->sem);
 481                return status;
 482        }
 483
 484        if (sme->ie == NULL || sme->ie_len == 0)
 485                ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
 486
 487        if (test_bit(CONNECTED, &vif->flags) &&
 488            vif->ssid_len == sme->ssid_len &&
 489            !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
 490                vif->reconnect_flag = true;
 491                status = ath6kl_wmi_reconnect_cmd(ar->wmi, vif->fw_vif_idx,
 492                                                  vif->req_bssid,
 493                                                  vif->ch_hint);
 494
 495                up(&ar->sem);
 496                if (status) {
 497                        ath6kl_err("wmi_reconnect_cmd failed\n");
 498                        return -EIO;
 499                }
 500                return 0;
 501        } else if (vif->ssid_len == sme->ssid_len &&
 502                   !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
 503                ath6kl_disconnect(vif);
 504        }
 505
 506        memset(vif->ssid, 0, sizeof(vif->ssid));
 507        vif->ssid_len = sme->ssid_len;
 508        memcpy(vif->ssid, sme->ssid, sme->ssid_len);
 509
 510        if (sme->channel)
 511                vif->ch_hint = sme->channel->center_freq;
 512
 513        memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
 514        if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
 515                memcpy(vif->req_bssid, sme->bssid, sizeof(vif->req_bssid));
 516
 517        ath6kl_set_wpa_version(vif, sme->crypto.wpa_versions);
 518
 519        status = ath6kl_set_auth_type(vif, sme->auth_type);
 520        if (status) {
 521                up(&ar->sem);
 522                return status;
 523        }
 524
 525        if (sme->crypto.n_ciphers_pairwise)
 526                ath6kl_set_cipher(vif, sme->crypto.ciphers_pairwise[0], true);
 527        else
 528                ath6kl_set_cipher(vif, 0, true);
 529
 530        ath6kl_set_cipher(vif, sme->crypto.cipher_group, false);
 531
 532        if (sme->crypto.n_akm_suites)
 533                ath6kl_set_key_mgmt(vif, sme->crypto.akm_suites[0]);
 534
 535        if ((sme->key_len) &&
 536            (vif->auth_mode == NONE_AUTH) &&
 537            (vif->prwise_crypto == WEP_CRYPT)) {
 538                struct ath6kl_key *key = NULL;
 539
 540                if (sme->key_idx > WMI_MAX_KEY_INDEX) {
 541                        ath6kl_err("key index %d out of bounds\n",
 542                                   sme->key_idx);
 543                        up(&ar->sem);
 544                        return -ENOENT;
 545                }
 546
 547                key = &vif->keys[sme->key_idx];
 548                key->key_len = sme->key_len;
 549                memcpy(key->key, sme->key, key->key_len);
 550                key->cipher = vif->prwise_crypto;
 551                vif->def_txkey_index = sme->key_idx;
 552
 553                ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, sme->key_idx,
 554                                      vif->prwise_crypto,
 555                                      GROUP_USAGE | TX_USAGE,
 556                                      key->key_len,
 557                                      NULL, 0,
 558                                      key->key, KEY_OP_INIT_VAL, NULL,
 559                                      NO_SYNC_WMIFLAG);
 560        }
 561
 562        if (!ar->usr_bss_filter) {
 563                clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
 564                if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
 565                                             ALL_BSS_FILTER, 0) != 0) {
 566                        ath6kl_err("couldn't set bss filtering\n");
 567                        up(&ar->sem);
 568                        return -EIO;
 569                }
 570        }
 571
 572        vif->nw_type = vif->next_mode;
 573
 574        if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
 575                nw_subtype = SUBTYPE_P2PCLIENT;
 576
 577        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 578                   "%s: connect called with authmode %d dot11 auth %d"
 579                   " PW crypto %d PW crypto len %d GRP crypto %d"
 580                   " GRP crypto len %d channel hint %u\n",
 581                   __func__,
 582                   vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
 583                   vif->prwise_crypto_len, vif->grp_crypto,
 584                   vif->grp_crypto_len, vif->ch_hint);
 585
 586        vif->reconnect_flag = 0;
 587
 588        if (vif->nw_type == INFRA_NETWORK) {
 589                interval = max_t(u16, vif->listen_intvl_t,
 590                                 ATH6KL_MAX_WOW_LISTEN_INTL);
 591                status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
 592                                                       interval,
 593                                                       0);
 594                if (status) {
 595                        ath6kl_err("couldn't set listen intervel\n");
 596                        up(&ar->sem);
 597                        return status;
 598                }
 599        }
 600
 601        status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
 602                                        vif->dot11_auth_mode, vif->auth_mode,
 603                                        vif->prwise_crypto,
 604                                        vif->prwise_crypto_len,
 605                                        vif->grp_crypto, vif->grp_crypto_len,
 606                                        vif->ssid_len, vif->ssid,
 607                                        vif->req_bssid, vif->ch_hint,
 608                                        ar->connect_ctrl_flags, nw_subtype);
 609
 610        up(&ar->sem);
 611
 612        if (status == -EINVAL) {
 613                memset(vif->ssid, 0, sizeof(vif->ssid));
 614                vif->ssid_len = 0;
 615                ath6kl_err("invalid request\n");
 616                return -ENOENT;
 617        } else if (status) {
 618                ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
 619                return -EIO;
 620        }
 621
 622        if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
 623            ((vif->auth_mode == WPA_PSK_AUTH) ||
 624             (vif->auth_mode == WPA2_PSK_AUTH))) {
 625                mod_timer(&vif->disconnect_timer,
 626                          jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
 627        }
 628
 629        ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
 630        set_bit(CONNECT_PEND, &vif->flags);
 631
 632        return 0;
 633}
 634
 635static struct cfg80211_bss *
 636ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
 637                         enum network_type nw_type,
 638                         const u8 *bssid,
 639                         struct ieee80211_channel *chan,
 640                         const u8 *beacon_ie,
 641                         size_t beacon_ie_len)
 642{
 643        struct ath6kl *ar = vif->ar;
 644        struct cfg80211_bss *bss;
 645        u16 cap_mask, cap_val;
 646        u8 *ie;
 647
 648        if (nw_type & ADHOC_NETWORK) {
 649                cap_mask = WLAN_CAPABILITY_IBSS;
 650                cap_val = WLAN_CAPABILITY_IBSS;
 651        } else {
 652                cap_mask = WLAN_CAPABILITY_ESS;
 653                cap_val = WLAN_CAPABILITY_ESS;
 654        }
 655
 656        bss = cfg80211_get_bss(ar->wiphy, chan, bssid,
 657                               vif->ssid, vif->ssid_len,
 658                               cap_mask, cap_val);
 659        if (bss == NULL) {
 660                /*
 661                 * Since cfg80211 may not yet know about the BSS,
 662                 * generate a partial entry until the first BSS info
 663                 * event becomes available.
 664                 *
 665                 * Prepend SSID element since it is not included in the Beacon
 666                 * IEs from the target.
 667                 */
 668                ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL);
 669                if (ie == NULL)
 670                        return NULL;
 671                ie[0] = WLAN_EID_SSID;
 672                ie[1] = vif->ssid_len;
 673                memcpy(ie + 2, vif->ssid, vif->ssid_len);
 674                memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
 675                bss = cfg80211_inform_bss(ar->wiphy, chan,
 676                                          bssid, 0, cap_val, 100,
 677                                          ie, 2 + vif->ssid_len + beacon_ie_len,
 678                                          0, GFP_KERNEL);
 679                if (bss)
 680                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to "
 681                                   "cfg80211\n", bssid);
 682                kfree(ie);
 683        } else
 684                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n");
 685
 686        return bss;
 687}
 688
 689void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
 690                                   u8 *bssid, u16 listen_intvl,
 691                                   u16 beacon_intvl,
 692                                   enum network_type nw_type,
 693                                   u8 beacon_ie_len, u8 assoc_req_len,
 694                                   u8 assoc_resp_len, u8 *assoc_info)
 695{
 696        struct ieee80211_channel *chan;
 697        struct ath6kl *ar = vif->ar;
 698        struct cfg80211_bss *bss;
 699
 700        /* capinfo + listen interval */
 701        u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
 702
 703        /* capinfo + status code +  associd */
 704        u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16);
 705
 706        u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset;
 707        u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
 708            assoc_resp_ie_offset;
 709
 710        assoc_req_len -= assoc_req_ie_offset;
 711        assoc_resp_len -= assoc_resp_ie_offset;
 712
 713        /*
 714         * Store Beacon interval here; DTIM period will be available only once
 715         * a Beacon frame from the AP is seen.
 716         */
 717        vif->assoc_bss_beacon_int = beacon_intvl;
 718        clear_bit(DTIM_PERIOD_AVAIL, &vif->flags);
 719
 720        if (nw_type & ADHOC_NETWORK) {
 721                if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
 722                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 723                                   "%s: ath6k not in ibss mode\n", __func__);
 724                        return;
 725                }
 726        }
 727
 728        if (nw_type & INFRA_NETWORK) {
 729                if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
 730                    vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
 731                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 732                                   "%s: ath6k not in station mode\n", __func__);
 733                        return;
 734                }
 735        }
 736
 737        chan = ieee80211_get_channel(ar->wiphy, (int) channel);
 738
 739        bss = ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan,
 740                                       assoc_info, beacon_ie_len);
 741        if (!bss) {
 742                ath6kl_err("could not add cfg80211 bss entry\n");
 743                return;
 744        }
 745
 746        if (nw_type & ADHOC_NETWORK) {
 747                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
 748                           nw_type & ADHOC_CREATOR ? "creator" : "joiner");
 749                cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
 750                cfg80211_put_bss(bss);
 751                return;
 752        }
 753
 754        if (vif->sme_state == SME_CONNECTING) {
 755                /* inform connect result to cfg80211 */
 756                vif->sme_state = SME_CONNECTED;
 757                cfg80211_connect_result(vif->ndev, bssid,
 758                                        assoc_req_ie, assoc_req_len,
 759                                        assoc_resp_ie, assoc_resp_len,
 760                                        WLAN_STATUS_SUCCESS, GFP_KERNEL);
 761                cfg80211_put_bss(bss);
 762        } else if (vif->sme_state == SME_CONNECTED) {
 763                /* inform roam event to cfg80211 */
 764                cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len,
 765                                    assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
 766        }
 767}
 768
 769static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
 770                                      struct net_device *dev, u16 reason_code)
 771{
 772        struct ath6kl *ar = ath6kl_priv(dev);
 773        struct ath6kl_vif *vif = netdev_priv(dev);
 774
 775        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
 776                   reason_code);
 777
 778        ath6kl_cfg80211_sscan_disable(vif);
 779
 780        if (!ath6kl_cfg80211_ready(vif))
 781                return -EIO;
 782
 783        if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
 784                ath6kl_err("busy, destroy in progress\n");
 785                return -EBUSY;
 786        }
 787
 788        if (down_interruptible(&ar->sem)) {
 789                ath6kl_err("busy, couldn't get access\n");
 790                return -ERESTARTSYS;
 791        }
 792
 793        vif->reconnect_flag = 0;
 794        ath6kl_disconnect(vif);
 795        memset(vif->ssid, 0, sizeof(vif->ssid));
 796        vif->ssid_len = 0;
 797
 798        if (!test_bit(SKIP_SCAN, &ar->flag))
 799                memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
 800
 801        up(&ar->sem);
 802
 803        vif->sme_state = SME_DISCONNECTED;
 804
 805        return 0;
 806}
 807
 808void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
 809                                      u8 *bssid, u8 assoc_resp_len,
 810                                      u8 *assoc_info, u16 proto_reason)
 811{
 812        struct ath6kl *ar = vif->ar;
 813
 814        if (vif->scan_req) {
 815                cfg80211_scan_done(vif->scan_req, true);
 816                vif->scan_req = NULL;
 817        }
 818
 819        if (vif->nw_type & ADHOC_NETWORK) {
 820                if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
 821                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 822                                   "%s: ath6k not in ibss mode\n", __func__);
 823                        return;
 824                }
 825                memset(bssid, 0, ETH_ALEN);
 826                cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
 827                return;
 828        }
 829
 830        if (vif->nw_type & INFRA_NETWORK) {
 831                if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
 832                    vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
 833                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 834                                   "%s: ath6k not in station mode\n", __func__);
 835                        return;
 836                }
 837        }
 838
 839        /*
 840         * Send a disconnect command to target when a disconnect event is
 841         * received with reason code other than 3 (DISCONNECT_CMD - disconnect
 842         * request from host) to make the firmware stop trying to connect even
 843         * after giving disconnect event. There will be one more disconnect
 844         * event for this disconnect command with reason code DISCONNECT_CMD
 845         * which will be notified to cfg80211.
 846         */
 847
 848        if (reason != DISCONNECT_CMD) {
 849                ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
 850                return;
 851        }
 852
 853        clear_bit(CONNECT_PEND, &vif->flags);
 854
 855        if (vif->sme_state == SME_CONNECTING) {
 856                cfg80211_connect_result(vif->ndev,
 857                                        bssid, NULL, 0,
 858                                        NULL, 0,
 859                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
 860                                        GFP_KERNEL);
 861        } else if (vif->sme_state == SME_CONNECTED) {
 862                cfg80211_disconnected(vif->ndev, reason,
 863                                      NULL, 0, GFP_KERNEL);
 864        }
 865
 866        vif->sme_state = SME_DISCONNECTED;
 867}
 868
 869static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 870                                struct cfg80211_scan_request *request)
 871{
 872        struct ath6kl *ar = ath6kl_priv(ndev);
 873        struct ath6kl_vif *vif = netdev_priv(ndev);
 874        s8 n_channels = 0;
 875        u16 *channels = NULL;
 876        int ret = 0;
 877        u32 force_fg_scan = 0;
 878
 879        if (!ath6kl_cfg80211_ready(vif))
 880                return -EIO;
 881
 882        ath6kl_cfg80211_sscan_disable(vif);
 883
 884        if (!ar->usr_bss_filter) {
 885                clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
 886                ret = ath6kl_wmi_bssfilter_cmd(
 887                        ar->wmi, vif->fw_vif_idx,
 888                        (test_bit(CONNECTED, &vif->flags) ?
 889                         ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
 890                if (ret) {
 891                        ath6kl_err("couldn't set bss filtering\n");
 892                        return ret;
 893                }
 894        }
 895
 896        if (request->n_ssids && request->ssids[0].ssid_len) {
 897                u8 i;
 898
 899                if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
 900                        request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
 901
 902                for (i = 0; i < request->n_ssids; i++)
 903                        ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
 904                                                  i + 1, SPECIFIC_SSID_FLAG,
 905                                                  request->ssids[i].ssid_len,
 906                                                  request->ssids[i].ssid);
 907        }
 908
 909        /* this also clears IE in fw if it's not set */
 910        ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
 911                                       WMI_FRAME_PROBE_REQ,
 912                                       request->ie, request->ie_len);
 913        if (ret) {
 914                ath6kl_err("failed to set Probe Request appie for "
 915                           "scan");
 916                return ret;
 917        }
 918
 919        /*
 920         * Scan only the requested channels if the request specifies a set of
 921         * channels. If the list is longer than the target supports, do not
 922         * configure the list and instead, scan all available channels.
 923         */
 924        if (request->n_channels > 0 &&
 925            request->n_channels <= WMI_MAX_CHANNELS) {
 926                u8 i;
 927
 928                n_channels = request->n_channels;
 929
 930                channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
 931                if (channels == NULL) {
 932                        ath6kl_warn("failed to set scan channels, "
 933                                    "scan all channels");
 934                        n_channels = 0;
 935                }
 936
 937                for (i = 0; i < n_channels; i++)
 938                        channels[i] = request->channels[i]->center_freq;
 939        }
 940
 941        if (test_bit(CONNECTED, &vif->flags))
 942                force_fg_scan = 1;
 943
 944        if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
 945                     ar->fw_capabilities)) {
 946                /*
 947                 * If capable of doing P2P mgmt operations using
 948                 * station interface, send additional information like
 949                 * supported rates to advertise and xmit rates for
 950                 * probe requests
 951                 */
 952                ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
 953                                                WMI_LONG_SCAN, force_fg_scan,
 954                                                false, 0,
 955                                                ATH6KL_FG_SCAN_INTERVAL,
 956                                                n_channels, channels,
 957                                                request->no_cck,
 958                                                request->rates);
 959        } else {
 960                ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
 961                                                WMI_LONG_SCAN, force_fg_scan,
 962                                                false, 0,
 963                                                ATH6KL_FG_SCAN_INTERVAL,
 964                                                n_channels, channels);
 965        }
 966        if (ret)
 967                ath6kl_err("wmi_startscan_cmd failed\n");
 968        else
 969                vif->scan_req = request;
 970
 971        kfree(channels);
 972
 973        return ret;
 974}
 975
 976void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
 977{
 978        struct ath6kl *ar = vif->ar;
 979        int i;
 980
 981        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
 982                   aborted ? " aborted" : "");
 983
 984        if (!vif->scan_req)
 985                return;
 986
 987        if (aborted)
 988                goto out;
 989
 990        if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
 991                for (i = 0; i < vif->scan_req->n_ssids; i++) {
 992                        ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
 993                                                  i + 1, DISABLE_SSID_FLAG,
 994                                                  0, NULL);
 995                }
 996        }
 997
 998out:
 999        cfg80211_scan_done(vif->scan_req, aborted);
1000        vif->scan_req = NULL;
1001}
1002
1003static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1004                                   u8 key_index, bool pairwise,
1005                                   const u8 *mac_addr,
1006                                   struct key_params *params)
1007{
1008        struct ath6kl *ar = ath6kl_priv(ndev);
1009        struct ath6kl_vif *vif = netdev_priv(ndev);
1010        struct ath6kl_key *key = NULL;
1011        int seq_len;
1012        u8 key_usage;
1013        u8 key_type;
1014
1015        if (!ath6kl_cfg80211_ready(vif))
1016                return -EIO;
1017
1018        if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
1019                if (params->key_len != WMI_KRK_LEN)
1020                        return -EINVAL;
1021                return ath6kl_wmi_add_krk_cmd(ar->wmi, vif->fw_vif_idx,
1022                                              params->key);
1023        }
1024
1025        if (key_index > WMI_MAX_KEY_INDEX) {
1026                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1027                           "%s: key index %d out of bounds\n", __func__,
1028                           key_index);
1029                return -ENOENT;
1030        }
1031
1032        key = &vif->keys[key_index];
1033        memset(key, 0, sizeof(struct ath6kl_key));
1034
1035        if (pairwise)
1036                key_usage = PAIRWISE_USAGE;
1037        else
1038                key_usage = GROUP_USAGE;
1039
1040        seq_len = params->seq_len;
1041        if (params->cipher == WLAN_CIPHER_SUITE_SMS4 &&
1042            seq_len > ATH6KL_KEY_SEQ_LEN) {
1043                /* Only first half of the WPI PN is configured */
1044                seq_len = ATH6KL_KEY_SEQ_LEN;
1045        }
1046        if (params->key_len > WLAN_MAX_KEY_LEN ||
1047            seq_len > sizeof(key->seq))
1048                return -EINVAL;
1049
1050        key->key_len = params->key_len;
1051        memcpy(key->key, params->key, key->key_len);
1052        key->seq_len = seq_len;
1053        memcpy(key->seq, params->seq, key->seq_len);
1054        key->cipher = params->cipher;
1055
1056        switch (key->cipher) {
1057        case WLAN_CIPHER_SUITE_WEP40:
1058        case WLAN_CIPHER_SUITE_WEP104:
1059                key_type = WEP_CRYPT;
1060                break;
1061
1062        case WLAN_CIPHER_SUITE_TKIP:
1063                key_type = TKIP_CRYPT;
1064                break;
1065
1066        case WLAN_CIPHER_SUITE_CCMP:
1067                key_type = AES_CRYPT;
1068                break;
1069        case WLAN_CIPHER_SUITE_SMS4:
1070                key_type = WAPI_CRYPT;
1071                break;
1072
1073        default:
1074                return -ENOTSUPP;
1075        }
1076
1077        if (((vif->auth_mode == WPA_PSK_AUTH) ||
1078             (vif->auth_mode == WPA2_PSK_AUTH)) &&
1079            (key_usage & GROUP_USAGE))
1080                del_timer(&vif->disconnect_timer);
1081
1082        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1083                   "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
1084                   __func__, key_index, key->key_len, key_type,
1085                   key_usage, key->seq_len);
1086
1087        if (vif->nw_type == AP_NETWORK && !pairwise &&
1088            (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
1089             key_type == WAPI_CRYPT)) {
1090                ar->ap_mode_bkey.valid = true;
1091                ar->ap_mode_bkey.key_index = key_index;
1092                ar->ap_mode_bkey.key_type = key_type;
1093                ar->ap_mode_bkey.key_len = key->key_len;
1094                memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
1095                if (!test_bit(CONNECTED, &vif->flags)) {
1096                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
1097                                   "key configuration until AP mode has been "
1098                                   "started\n");
1099                        /*
1100                         * The key will be set in ath6kl_connect_ap_mode() once
1101                         * the connected event is received from the target.
1102                         */
1103                        return 0;
1104                }
1105        }
1106
1107        if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
1108            !test_bit(CONNECTED, &vif->flags)) {
1109                /*
1110                 * Store the key locally so that it can be re-configured after
1111                 * the AP mode has properly started
1112                 * (ath6kl_install_statioc_wep_keys).
1113                 */
1114                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
1115                           "until AP mode has been started\n");
1116                vif->wep_key_list[key_index].key_len = key->key_len;
1117                memcpy(vif->wep_key_list[key_index].key, key->key,
1118                       key->key_len);
1119                return 0;
1120        }
1121
1122        return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index,
1123                                     key_type, key_usage, key->key_len,
1124                                     key->seq, key->seq_len, key->key,
1125                                     KEY_OP_INIT_VAL,
1126                                     (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
1127}
1128
1129static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1130                                   u8 key_index, bool pairwise,
1131                                   const u8 *mac_addr)
1132{
1133        struct ath6kl *ar = ath6kl_priv(ndev);
1134        struct ath6kl_vif *vif = netdev_priv(ndev);
1135
1136        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1137
1138        if (!ath6kl_cfg80211_ready(vif))
1139                return -EIO;
1140
1141        if (key_index > WMI_MAX_KEY_INDEX) {
1142                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1143                           "%s: key index %d out of bounds\n", __func__,
1144                           key_index);
1145                return -ENOENT;
1146        }
1147
1148        if (!vif->keys[key_index].key_len) {
1149                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1150                           "%s: index %d is empty\n", __func__, key_index);
1151                return 0;
1152        }
1153
1154        vif->keys[key_index].key_len = 0;
1155
1156        return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
1157}
1158
1159static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1160                                   u8 key_index, bool pairwise,
1161                                   const u8 *mac_addr, void *cookie,
1162                                   void (*callback) (void *cookie,
1163                                                     struct key_params *))
1164{
1165        struct ath6kl_vif *vif = netdev_priv(ndev);
1166        struct ath6kl_key *key = NULL;
1167        struct key_params params;
1168
1169        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1170
1171        if (!ath6kl_cfg80211_ready(vif))
1172                return -EIO;
1173
1174        if (key_index > WMI_MAX_KEY_INDEX) {
1175                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1176                           "%s: key index %d out of bounds\n", __func__,
1177                           key_index);
1178                return -ENOENT;
1179        }
1180
1181        key = &vif->keys[key_index];
1182        memset(&params, 0, sizeof(params));
1183        params.cipher = key->cipher;
1184        params.key_len = key->key_len;
1185        params.seq_len = key->seq_len;
1186        params.seq = key->seq;
1187        params.key = key->key;
1188
1189        callback(cookie, &params);
1190
1191        return key->key_len ? 0 : -ENOENT;
1192}
1193
1194static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
1195                                           struct net_device *ndev,
1196                                           u8 key_index, bool unicast,
1197                                           bool multicast)
1198{
1199        struct ath6kl *ar = ath6kl_priv(ndev);
1200        struct ath6kl_vif *vif = netdev_priv(ndev);
1201        struct ath6kl_key *key = NULL;
1202        u8 key_usage;
1203        enum crypto_type key_type = NONE_CRYPT;
1204
1205        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1206
1207        if (!ath6kl_cfg80211_ready(vif))
1208                return -EIO;
1209
1210        if (key_index > WMI_MAX_KEY_INDEX) {
1211                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1212                           "%s: key index %d out of bounds\n",
1213                           __func__, key_index);
1214                return -ENOENT;
1215        }
1216
1217        if (!vif->keys[key_index].key_len) {
1218                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1219                           __func__, key_index);
1220                return -EINVAL;
1221        }
1222
1223        vif->def_txkey_index = key_index;
1224        key = &vif->keys[vif->def_txkey_index];
1225        key_usage = GROUP_USAGE;
1226        if (vif->prwise_crypto == WEP_CRYPT)
1227                key_usage |= TX_USAGE;
1228        if (unicast)
1229                key_type = vif->prwise_crypto;
1230        if (multicast)
1231                key_type = vif->grp_crypto;
1232
1233        if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
1234                return 0; /* Delay until AP mode has been started */
1235
1236        return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1237                                     vif->def_txkey_index,
1238                                     key_type, key_usage,
1239                                     key->key_len, key->seq, key->seq_len,
1240                                     key->key,
1241                                     KEY_OP_INIT_VAL, NULL,
1242                                     SYNC_BOTH_WMIFLAG);
1243}
1244
1245void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
1246                                       bool ismcast)
1247{
1248        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1249                   "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1250
1251        cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
1252                                     (ismcast ? NL80211_KEYTYPE_GROUP :
1253                                      NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1254                                     GFP_KERNEL);
1255}
1256
1257static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1258{
1259        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1260        struct ath6kl_vif *vif;
1261        int ret;
1262
1263        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1264                   changed);
1265
1266        vif = ath6kl_vif_first(ar);
1267        if (!vif)
1268                return -EIO;
1269
1270        if (!ath6kl_cfg80211_ready(vif))
1271                return -EIO;
1272
1273        if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1274                ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1275                if (ret != 0) {
1276                        ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1277                        return -EIO;
1278                }
1279        }
1280
1281        return 0;
1282}
1283
1284/*
1285 * The type nl80211_tx_power_setting replaces the following
1286 * data type from 2.6.36 onwards
1287*/
1288static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1289                                       enum nl80211_tx_power_setting type,
1290                                       int mbm)
1291{
1292        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1293        struct ath6kl_vif *vif;
1294        int dbm = MBM_TO_DBM(mbm);
1295
1296        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1297                   type, dbm);
1298
1299        vif = ath6kl_vif_first(ar);
1300        if (!vif)
1301                return -EIO;
1302
1303        if (!ath6kl_cfg80211_ready(vif))
1304                return -EIO;
1305
1306        switch (type) {
1307        case NL80211_TX_POWER_AUTOMATIC:
1308                return 0;
1309        case NL80211_TX_POWER_LIMITED:
1310                ar->tx_pwr = dbm;
1311                break;
1312        default:
1313                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1314                           __func__, type);
1315                return -EOPNOTSUPP;
1316        }
1317
1318        ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, dbm);
1319
1320        return 0;
1321}
1322
1323static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1324{
1325        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1326        struct ath6kl_vif *vif;
1327
1328        vif = ath6kl_vif_first(ar);
1329        if (!vif)
1330                return -EIO;
1331
1332        if (!ath6kl_cfg80211_ready(vif))
1333                return -EIO;
1334
1335        if (test_bit(CONNECTED, &vif->flags)) {
1336                ar->tx_pwr = 0;
1337
1338                if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
1339                        ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1340                        return -EIO;
1341                }
1342
1343                wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1344                                                 5 * HZ);
1345
1346                if (signal_pending(current)) {
1347                        ath6kl_err("target did not respond\n");
1348                        return -EINTR;
1349                }
1350        }
1351
1352        *dbm = ar->tx_pwr;
1353        return 0;
1354}
1355
1356static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1357                                          struct net_device *dev,
1358                                          bool pmgmt, int timeout)
1359{
1360        struct ath6kl *ar = ath6kl_priv(dev);
1361        struct wmi_power_mode_cmd mode;
1362        struct ath6kl_vif *vif = netdev_priv(dev);
1363
1364        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1365                   __func__, pmgmt, timeout);
1366
1367        if (!ath6kl_cfg80211_ready(vif))
1368                return -EIO;
1369
1370        if (pmgmt) {
1371                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1372                mode.pwr_mode = REC_POWER;
1373        } else {
1374                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1375                mode.pwr_mode = MAX_PERF_POWER;
1376        }
1377
1378        if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
1379                                     mode.pwr_mode) != 0) {
1380                ath6kl_err("wmi_powermode_cmd failed\n");
1381                return -EIO;
1382        }
1383
1384        return 0;
1385}
1386
1387static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
1388                                                    char *name,
1389                                                    enum nl80211_iftype type,
1390                                                    u32 *flags,
1391                                                    struct vif_params *params)
1392{
1393        struct ath6kl *ar = wiphy_priv(wiphy);
1394        struct net_device *ndev;
1395        u8 if_idx, nw_type;
1396
1397        if (ar->num_vif == ar->vif_max) {
1398                ath6kl_err("Reached maximum number of supported vif\n");
1399                return ERR_PTR(-EINVAL);
1400        }
1401
1402        if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
1403                ath6kl_err("Not a supported interface type\n");
1404                return ERR_PTR(-EINVAL);
1405        }
1406
1407        ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
1408        if (!ndev)
1409                return ERR_PTR(-ENOMEM);
1410
1411        ar->num_vif++;
1412
1413        return ndev;
1414}
1415
1416static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
1417                                     struct net_device *ndev)
1418{
1419        struct ath6kl *ar = wiphy_priv(wiphy);
1420        struct ath6kl_vif *vif = netdev_priv(ndev);
1421
1422        spin_lock_bh(&ar->list_lock);
1423        list_del(&vif->list);
1424        spin_unlock_bh(&ar->list_lock);
1425
1426        ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
1427
1428        ath6kl_cfg80211_vif_cleanup(vif);
1429
1430        return 0;
1431}
1432
1433static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1434                                        struct net_device *ndev,
1435                                        enum nl80211_iftype type, u32 *flags,
1436                                        struct vif_params *params)
1437{
1438        struct ath6kl_vif *vif = netdev_priv(ndev);
1439
1440        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1441
1442        switch (type) {
1443        case NL80211_IFTYPE_STATION:
1444                vif->next_mode = INFRA_NETWORK;
1445                break;
1446        case NL80211_IFTYPE_ADHOC:
1447                vif->next_mode = ADHOC_NETWORK;
1448                break;
1449        case NL80211_IFTYPE_AP:
1450                vif->next_mode = AP_NETWORK;
1451                break;
1452        case NL80211_IFTYPE_P2P_CLIENT:
1453                vif->next_mode = INFRA_NETWORK;
1454                break;
1455        case NL80211_IFTYPE_P2P_GO:
1456                vif->next_mode = AP_NETWORK;
1457                break;
1458        default:
1459                ath6kl_err("invalid interface type %u\n", type);
1460                return -EOPNOTSUPP;
1461        }
1462
1463        vif->wdev.iftype = type;
1464
1465        return 0;
1466}
1467
1468static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1469                                     struct net_device *dev,
1470                                     struct cfg80211_ibss_params *ibss_param)
1471{
1472        struct ath6kl *ar = ath6kl_priv(dev);
1473        struct ath6kl_vif *vif = netdev_priv(dev);
1474        int status;
1475
1476        if (!ath6kl_cfg80211_ready(vif))
1477                return -EIO;
1478
1479        vif->ssid_len = ibss_param->ssid_len;
1480        memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
1481
1482        if (ibss_param->channel)
1483                vif->ch_hint = ibss_param->channel->center_freq;
1484
1485        if (ibss_param->channel_fixed) {
1486                /*
1487                 * TODO: channel_fixed: The channel should be fixed, do not
1488                 * search for IBSSs to join on other channels. Target
1489                 * firmware does not support this feature, needs to be
1490                 * updated.
1491                 */
1492                return -EOPNOTSUPP;
1493        }
1494
1495        memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
1496        if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
1497                memcpy(vif->req_bssid, ibss_param->bssid,
1498                       sizeof(vif->req_bssid));
1499
1500        ath6kl_set_wpa_version(vif, 0);
1501
1502        status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
1503        if (status)
1504                return status;
1505
1506        if (ibss_param->privacy) {
1507                ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
1508                ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
1509        } else {
1510                ath6kl_set_cipher(vif, 0, true);
1511                ath6kl_set_cipher(vif, 0, false);
1512        }
1513
1514        vif->nw_type = vif->next_mode;
1515
1516        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1517                   "%s: connect called with authmode %d dot11 auth %d"
1518                   " PW crypto %d PW crypto len %d GRP crypto %d"
1519                   " GRP crypto len %d channel hint %u\n",
1520                   __func__,
1521                   vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
1522                   vif->prwise_crypto_len, vif->grp_crypto,
1523                   vif->grp_crypto_len, vif->ch_hint);
1524
1525        status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
1526                                        vif->dot11_auth_mode, vif->auth_mode,
1527                                        vif->prwise_crypto,
1528                                        vif->prwise_crypto_len,
1529                                        vif->grp_crypto, vif->grp_crypto_len,
1530                                        vif->ssid_len, vif->ssid,
1531                                        vif->req_bssid, vif->ch_hint,
1532                                        ar->connect_ctrl_flags, SUBTYPE_NONE);
1533        set_bit(CONNECT_PEND, &vif->flags);
1534
1535        return 0;
1536}
1537
1538static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1539                                      struct net_device *dev)
1540{
1541        struct ath6kl_vif *vif = netdev_priv(dev);
1542
1543        if (!ath6kl_cfg80211_ready(vif))
1544                return -EIO;
1545
1546        ath6kl_disconnect(vif);
1547        memset(vif->ssid, 0, sizeof(vif->ssid));
1548        vif->ssid_len = 0;
1549
1550        return 0;
1551}
1552
1553static const u32 cipher_suites[] = {
1554        WLAN_CIPHER_SUITE_WEP40,
1555        WLAN_CIPHER_SUITE_WEP104,
1556        WLAN_CIPHER_SUITE_TKIP,
1557        WLAN_CIPHER_SUITE_CCMP,
1558        CCKM_KRK_CIPHER_SUITE,
1559        WLAN_CIPHER_SUITE_SMS4,
1560};
1561
1562static bool is_rate_legacy(s32 rate)
1563{
1564        static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1565                6000, 9000, 12000, 18000, 24000,
1566                36000, 48000, 54000
1567        };
1568        u8 i;
1569
1570        for (i = 0; i < ARRAY_SIZE(legacy); i++)
1571                if (rate == legacy[i])
1572                        return true;
1573
1574        return false;
1575}
1576
1577static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1578{
1579        static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1580                52000, 58500, 65000, 72200
1581        };
1582        u8 i;
1583
1584        for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1585                if (rate == ht20[i]) {
1586                        if (i == ARRAY_SIZE(ht20) - 1)
1587                                /* last rate uses sgi */
1588                                *sgi = true;
1589                        else
1590                                *sgi = false;
1591
1592                        *mcs = i;
1593                        return true;
1594                }
1595        }
1596        return false;
1597}
1598
1599static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1600{
1601        static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1602                81000, 108000, 121500, 135000,
1603                150000
1604        };
1605        u8 i;
1606
1607        for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1608                if (rate == ht40[i]) {
1609                        if (i == ARRAY_SIZE(ht40) - 1)
1610                                /* last rate uses sgi */
1611                                *sgi = true;
1612                        else
1613                                *sgi = false;
1614
1615                        *mcs = i;
1616                        return true;
1617                }
1618        }
1619
1620        return false;
1621}
1622
1623static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1624                              u8 *mac, struct station_info *sinfo)
1625{
1626        struct ath6kl *ar = ath6kl_priv(dev);
1627        struct ath6kl_vif *vif = netdev_priv(dev);
1628        long left;
1629        bool sgi;
1630        s32 rate;
1631        int ret;
1632        u8 mcs;
1633
1634        if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
1635                return -ENOENT;
1636
1637        if (down_interruptible(&ar->sem))
1638                return -EBUSY;
1639
1640        set_bit(STATS_UPDATE_PEND, &vif->flags);
1641
1642        ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
1643
1644        if (ret != 0) {
1645                up(&ar->sem);
1646                return -EIO;
1647        }
1648
1649        left = wait_event_interruptible_timeout(ar->event_wq,
1650                                                !test_bit(STATS_UPDATE_PEND,
1651                                                          &vif->flags),
1652                                                WMI_TIMEOUT);
1653
1654        up(&ar->sem);
1655
1656        if (left == 0)
1657                return -ETIMEDOUT;
1658        else if (left < 0)
1659                return left;
1660
1661        if (vif->target_stats.rx_byte) {
1662                sinfo->rx_bytes = vif->target_stats.rx_byte;
1663                sinfo->filled |= STATION_INFO_RX_BYTES;
1664                sinfo->rx_packets = vif->target_stats.rx_pkt;
1665                sinfo->filled |= STATION_INFO_RX_PACKETS;
1666        }
1667
1668        if (vif->target_stats.tx_byte) {
1669                sinfo->tx_bytes = vif->target_stats.tx_byte;
1670                sinfo->filled |= STATION_INFO_TX_BYTES;
1671                sinfo->tx_packets = vif->target_stats.tx_pkt;
1672                sinfo->filled |= STATION_INFO_TX_PACKETS;
1673        }
1674
1675        sinfo->signal = vif->target_stats.cs_rssi;
1676        sinfo->filled |= STATION_INFO_SIGNAL;
1677
1678        rate = vif->target_stats.tx_ucast_rate;
1679
1680        if (is_rate_legacy(rate)) {
1681                sinfo->txrate.legacy = rate / 100;
1682        } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1683                if (sgi) {
1684                        sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1685                        sinfo->txrate.mcs = mcs - 1;
1686                } else {
1687                        sinfo->txrate.mcs = mcs;
1688                }
1689
1690                sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1691        } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1692                if (sgi) {
1693                        sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1694                        sinfo->txrate.mcs = mcs - 1;
1695                } else {
1696                        sinfo->txrate.mcs = mcs;
1697                }
1698
1699                sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1700                sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1701        } else {
1702                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1703                           "invalid rate from stats: %d\n", rate);
1704                ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
1705                return 0;
1706        }
1707
1708        sinfo->filled |= STATION_INFO_TX_BITRATE;
1709
1710        if (test_bit(CONNECTED, &vif->flags) &&
1711            test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
1712            vif->nw_type == INFRA_NETWORK) {
1713                sinfo->filled |= STATION_INFO_BSS_PARAM;
1714                sinfo->bss_param.flags = 0;
1715                sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
1716                sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
1717        }
1718
1719        return 0;
1720}
1721
1722static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1723                            struct cfg80211_pmksa *pmksa)
1724{
1725        struct ath6kl *ar = ath6kl_priv(netdev);
1726        struct ath6kl_vif *vif = netdev_priv(netdev);
1727
1728        return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
1729                                       pmksa->pmkid, true);
1730}
1731
1732static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1733                            struct cfg80211_pmksa *pmksa)
1734{
1735        struct ath6kl *ar = ath6kl_priv(netdev);
1736        struct ath6kl_vif *vif = netdev_priv(netdev);
1737
1738        return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
1739                                       pmksa->pmkid, false);
1740}
1741
1742static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1743{
1744        struct ath6kl *ar = ath6kl_priv(netdev);
1745        struct ath6kl_vif *vif = netdev_priv(netdev);
1746
1747        if (test_bit(CONNECTED, &vif->flags))
1748                return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
1749                                               vif->bssid, NULL, false);
1750        return 0;
1751}
1752
1753static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
1754                          struct cfg80211_wowlan *wow, u32 *filter)
1755{
1756        int ret, pos;
1757        u8 mask[WOW_MASK_SIZE];
1758        u16 i;
1759
1760        /* Configure the patterns that we received from the user. */
1761        for (i = 0; i < wow->n_patterns; i++) {
1762
1763                /*
1764                 * Convert given nl80211 specific mask value to equivalent
1765                 * driver specific mask value and send it to the chip along
1766                 * with patterns. For example, If the mask value defined in
1767                 * struct cfg80211_wowlan is 0xA (equivalent binary is 1010),
1768                 * then equivalent driver specific mask value is
1769                 * "0xFF 0x00 0xFF 0x00".
1770                 */
1771                memset(&mask, 0, sizeof(mask));
1772                for (pos = 0; pos < wow->patterns[i].pattern_len; pos++) {
1773                        if (wow->patterns[i].mask[pos / 8] & (0x1 << (pos % 8)))
1774                                mask[pos] = 0xFF;
1775                }
1776                /*
1777                 * Note: Pattern's offset is not passed as part of wowlan
1778                 * parameter from CFG layer. So it's always passed as ZERO
1779                 * to the firmware. It means, given WOW patterns are always
1780                 * matched from the first byte of received pkt in the firmware.
1781                 */
1782                ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1783                                vif->fw_vif_idx, WOW_LIST_ID,
1784                                wow->patterns[i].pattern_len,
1785                                0 /* pattern offset */,
1786                                wow->patterns[i].pattern, mask);
1787                if (ret)
1788                        return ret;
1789        }
1790
1791        if (wow->disconnect)
1792                *filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1793
1794        if (wow->magic_pkt)
1795                *filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1796
1797        if (wow->gtk_rekey_failure)
1798                *filter |= WOW_FILTER_OPTION_GTK_ERROR;
1799
1800        if (wow->eap_identity_req)
1801                *filter |= WOW_FILTER_OPTION_EAP_REQ;
1802
1803        if (wow->four_way_handshake)
1804                *filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1805
1806        return 0;
1807}
1808
1809static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif)
1810{
1811        static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00,
1812                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1813                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1814                0x00, 0x08 };
1815        static const u8 unicst_mask[] = { 0x01, 0x00, 0x00,
1816                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1817                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1818                0x00, 0x7f };
1819        u8 unicst_offset = 0;
1820        static const u8 arp_pattern[] = { 0x08, 0x06 };
1821        static const u8 arp_mask[] = { 0xff, 0xff };
1822        u8 arp_offset = 20;
1823        static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1824        static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1825        u8 discvr_offset = 38;
1826        static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff,
1827                0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1828                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1829                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1830                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1831                0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ };
1832        static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff,
1833                0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1834                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1835                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1836                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1837                0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ };
1838        u8 dhcp_offset = 0;
1839        int ret;
1840
1841        /* Setup unicast IP, EAPOL-like and ARP pkt pattern */
1842        ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1843                        vif->fw_vif_idx, WOW_LIST_ID,
1844                        sizeof(unicst_pattern), unicst_offset,
1845                        unicst_pattern, unicst_mask);
1846        if (ret) {
1847                ath6kl_err("failed to add WOW unicast IP pattern\n");
1848                return ret;
1849        }
1850
1851        /* Setup all ARP pkt pattern */
1852        ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1853                        vif->fw_vif_idx, WOW_LIST_ID,
1854                        sizeof(arp_pattern), arp_offset,
1855                        arp_pattern, arp_mask);
1856        if (ret) {
1857                ath6kl_err("failed to add WOW ARP pattern\n");
1858                return ret;
1859        }
1860
1861        /*
1862         * Setup multicast pattern for mDNS 224.0.0.251,
1863         * SSDP 239.255.255.250 and LLMNR  224.0.0.252
1864         */
1865        ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1866                        vif->fw_vif_idx, WOW_LIST_ID,
1867                        sizeof(discvr_pattern), discvr_offset,
1868                        discvr_pattern, discvr_mask);
1869        if (ret) {
1870                ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
1871                return ret;
1872        }
1873
1874        /* Setup all DHCP broadcast pkt pattern */
1875        ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1876                        vif->fw_vif_idx, WOW_LIST_ID,
1877                        sizeof(dhcp_pattern), dhcp_offset,
1878                        dhcp_pattern, dhcp_mask);
1879        if (ret) {
1880                ath6kl_err("failed to add WOW DHCP broadcast pattern\n");
1881                return ret;
1882        }
1883
1884        return 0;
1885}
1886
1887static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
1888{
1889        struct net_device *ndev = vif->ndev;
1890        static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1891        static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1892        u8 discvr_offset = 38;
1893        u8 mac_mask[ETH_ALEN];
1894        int ret;
1895
1896        /* Setup unicast pkt pattern */
1897        memset(mac_mask, 0xff, ETH_ALEN);
1898        ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1899                                vif->fw_vif_idx, WOW_LIST_ID,
1900                                ETH_ALEN, 0, ndev->dev_addr,
1901                                mac_mask);
1902        if (ret) {
1903                ath6kl_err("failed to add WOW unicast pattern\n");
1904                return ret;
1905        }
1906
1907        /*
1908         * Setup multicast pattern for mDNS 224.0.0.251,
1909         * SSDP 239.255.255.250 and LLMNR 224.0.0.252
1910         */
1911        if ((ndev->flags & IFF_ALLMULTI) ||
1912            (ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) {
1913                ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1914                                vif->fw_vif_idx, WOW_LIST_ID,
1915                                sizeof(discvr_pattern), discvr_offset,
1916                                discvr_pattern, discvr_mask);
1917                if (ret) {
1918                        ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR "
1919                                   "pattern\n");
1920                        return ret;
1921                }
1922        }
1923
1924        return 0;
1925}
1926
1927static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1928{
1929        struct in_device *in_dev;
1930        struct in_ifaddr *ifa;
1931        struct ath6kl_vif *vif;
1932        int ret, left;
1933        u32 filter = 0;
1934        u16 i, bmiss_time;
1935        u8 index = 0;
1936        __be32 ips[MAX_IP_ADDRS];
1937
1938        vif = ath6kl_vif_first(ar);
1939        if (!vif)
1940                return -EIO;
1941
1942        if (!ath6kl_cfg80211_ready(vif))
1943                return -EIO;
1944
1945        if (!test_bit(CONNECTED, &vif->flags))
1946                return -ENOTCONN;
1947
1948        if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
1949                return -EINVAL;
1950
1951        /* Clear existing WOW patterns */
1952        for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
1953                ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
1954                                               WOW_LIST_ID, i);
1955
1956        /*
1957         * Skip the default WOW pattern configuration
1958         * if the driver receives any WOW patterns from
1959         * the user.
1960         */
1961        if (wow)
1962                ret = ath6kl_wow_usr(ar, vif, wow, &filter);
1963        else if (vif->nw_type == AP_NETWORK)
1964                ret = ath6kl_wow_ap(ar, vif);
1965        else
1966                ret = ath6kl_wow_sta(ar, vif);
1967
1968        if (ret)
1969                return ret;
1970
1971        netif_stop_queue(vif->ndev);
1972
1973        if (vif->nw_type != AP_NETWORK) {
1974                ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
1975                                                    ATH6KL_MAX_WOW_LISTEN_INTL,
1976                                                    0);
1977                if (ret)
1978                        return ret;
1979
1980                /* Set listen interval x 15 times as bmiss time */
1981                bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
1982                if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
1983                        bmiss_time = ATH6KL_MAX_BMISS_TIME;
1984
1985                ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
1986                                               bmiss_time, 0);
1987                if (ret)
1988                        return ret;
1989
1990                ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
1991                                                0xFFFF, 0, 0xFFFF, 0, 0, 0,
1992                                                0, 0, 0, 0);
1993                if (ret)
1994                        return ret;
1995        }
1996
1997        ar->state = ATH6KL_STATE_SUSPENDING;
1998
1999        /* Setup own IP addr for ARP agent. */
2000        in_dev = __in_dev_get_rtnl(vif->ndev);
2001        if (!in_dev)
2002                goto skip_arp;
2003
2004        ifa = in_dev->ifa_list;
2005        memset(&ips, 0, sizeof(ips));
2006
2007        /* Configure IP addr only if IP address count < MAX_IP_ADDRS */
2008        while (index < MAX_IP_ADDRS && ifa) {
2009                ips[index] = ifa->ifa_local;
2010                ifa = ifa->ifa_next;
2011                index++;
2012        }
2013
2014        if (ifa) {
2015                ath6kl_err("total IP addr count is exceeding fw limit\n");
2016                return -EINVAL;
2017        }
2018
2019        ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]);
2020        if (ret) {
2021                ath6kl_err("fail to setup ip for arp agent\n");
2022                return ret;
2023        }
2024
2025skip_arp:
2026        ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2027                                          ATH6KL_WOW_MODE_ENABLE,
2028                                          filter,
2029                                          WOW_HOST_REQ_DELAY);
2030        if (ret)
2031                return ret;
2032
2033        clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
2034
2035        ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2036                                                 ATH6KL_HOST_MODE_ASLEEP);
2037        if (ret)
2038                return ret;
2039
2040        left = wait_event_interruptible_timeout(ar->event_wq,
2041                        test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags),
2042                        WMI_TIMEOUT);
2043        if (left == 0) {
2044                ath6kl_warn("timeout, didn't get host sleep cmd "
2045                            "processed event\n");
2046                ret = -ETIMEDOUT;
2047        } else if (left < 0) {
2048                ath6kl_warn("error while waiting for host sleep cmd "
2049                            "processed event %d\n", left);
2050                ret = left;
2051        }
2052
2053        if (ar->tx_pending[ar->ctrl_ep]) {
2054                left = wait_event_interruptible_timeout(ar->event_wq,
2055                                ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
2056                if (left == 0) {
2057                        ath6kl_warn("clear wmi ctrl data timeout\n");
2058                        ret = -ETIMEDOUT;
2059                } else if (left < 0) {
2060                        ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
2061                        ret = left;
2062                }
2063        }
2064
2065        return ret;
2066}
2067
2068static int ath6kl_wow_resume(struct ath6kl *ar)
2069{
2070        struct ath6kl_vif *vif;
2071        int ret;
2072
2073        vif = ath6kl_vif_first(ar);
2074        if (!vif)
2075                return -EIO;
2076
2077        ar->state = ATH6KL_STATE_RESUMING;
2078
2079        ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2080                                                 ATH6KL_HOST_MODE_AWAKE);
2081        if (ret) {
2082                ath6kl_warn("Failed to configure host sleep mode for "
2083                            "wow resume: %d\n", ret);
2084                ar->state = ATH6KL_STATE_WOW;
2085                return ret;
2086        }
2087
2088        if (vif->nw_type != AP_NETWORK) {
2089                ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2090                                                0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2091                if (ret)
2092                        return ret;
2093
2094                ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
2095                                                    vif->listen_intvl_t, 0);
2096                if (ret)
2097                        return ret;
2098
2099                ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
2100                                               vif->bmiss_time_t, 0);
2101                if (ret)
2102                        return ret;
2103        }
2104
2105        ar->state = ATH6KL_STATE_ON;
2106
2107        netif_wake_queue(vif->ndev);
2108
2109        return 0;
2110}
2111
2112int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2113                            enum ath6kl_cfg_suspend_mode mode,
2114                            struct cfg80211_wowlan *wow)
2115{
2116        enum ath6kl_state prev_state;
2117        int ret;
2118
2119        switch (mode) {
2120        case ATH6KL_CFG_SUSPEND_WOW:
2121
2122                ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode suspend\n");
2123
2124                /* Flush all non control pkts in TX path */
2125                ath6kl_tx_data_cleanup(ar);
2126
2127                prev_state = ar->state;
2128
2129                ret = ath6kl_wow_suspend(ar, wow);
2130                if (ret) {
2131                        ar->state = prev_state;
2132                        return ret;
2133                }
2134
2135                ar->state = ATH6KL_STATE_WOW;
2136                break;
2137
2138        case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
2139
2140                ath6kl_cfg80211_stop_all(ar);
2141
2142                /* save the current power mode before enabling power save */
2143                ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2144
2145                ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
2146                if (ret) {
2147                        ath6kl_warn("wmi powermode command failed during suspend: %d\n",
2148                                    ret);
2149                }
2150
2151                ar->state = ATH6KL_STATE_DEEPSLEEP;
2152
2153                break;
2154
2155        case ATH6KL_CFG_SUSPEND_CUTPOWER:
2156
2157                ath6kl_cfg80211_stop_all(ar);
2158
2159                if (ar->state == ATH6KL_STATE_OFF) {
2160                        ath6kl_dbg(ATH6KL_DBG_SUSPEND,
2161                                   "suspend hw off, no action for cutpower\n");
2162                        break;
2163                }
2164
2165                ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
2166
2167                ret = ath6kl_init_hw_stop(ar);
2168                if (ret) {
2169                        ath6kl_warn("failed to stop hw during suspend: %d\n",
2170                                    ret);
2171                }
2172
2173                ar->state = ATH6KL_STATE_CUTPOWER;
2174
2175                break;
2176
2177        case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
2178                /*
2179                 * Nothing needed for schedule scan, firmware is already in
2180                 * wow mode and sleeping most of the time.
2181                 */
2182                break;
2183
2184        default:
2185                break;
2186        }
2187
2188        return 0;
2189}
2190EXPORT_SYMBOL(ath6kl_cfg80211_suspend);
2191
2192int ath6kl_cfg80211_resume(struct ath6kl *ar)
2193{
2194        int ret;
2195
2196        switch (ar->state) {
2197        case  ATH6KL_STATE_WOW:
2198                ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode resume\n");
2199
2200                ret = ath6kl_wow_resume(ar);
2201                if (ret) {
2202                        ath6kl_warn("wow mode resume failed: %d\n", ret);
2203                        return ret;
2204                }
2205
2206                break;
2207
2208        case ATH6KL_STATE_DEEPSLEEP:
2209                if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
2210                        ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
2211                                                       ar->wmi->saved_pwr_mode);
2212                        if (ret) {
2213                                ath6kl_warn("wmi powermode command failed during resume: %d\n",
2214                                            ret);
2215                        }
2216                }
2217
2218                ar->state = ATH6KL_STATE_ON;
2219
2220                break;
2221
2222        case ATH6KL_STATE_CUTPOWER:
2223                ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
2224
2225                ret = ath6kl_init_hw_start(ar);
2226                if (ret) {
2227                        ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
2228                        return ret;
2229                }
2230                break;
2231
2232        case ATH6KL_STATE_SCHED_SCAN:
2233                break;
2234
2235        default:
2236                break;
2237        }
2238
2239        return 0;
2240}
2241EXPORT_SYMBOL(ath6kl_cfg80211_resume);
2242
2243#ifdef CONFIG_PM
2244
2245/* hif layer decides what suspend mode to use */
2246static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
2247                                 struct cfg80211_wowlan *wow)
2248{
2249        struct ath6kl *ar = wiphy_priv(wiphy);
2250
2251        return ath6kl_hif_suspend(ar, wow);
2252}
2253
2254static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
2255{
2256        struct ath6kl *ar = wiphy_priv(wiphy);
2257
2258        return ath6kl_hif_resume(ar);
2259}
2260
2261/*
2262 * FIXME: WOW suspend mode is selected if the host sdio controller supports
2263 * both sdio irq wake up and keep power. The target pulls sdio data line to
2264 * wake up the host when WOW pattern matches. This causes sdio irq handler
2265 * is being called in the host side which internally hits ath6kl's RX path.
2266 *
2267 * Since sdio interrupt is not disabled, RX path executes even before
2268 * the host executes the actual resume operation from PM module.
2269 *
2270 * In the current scenario, WOW resume should happen before start processing
2271 * any data from the target. So It's required to perform WOW resume in RX path.
2272 * Ideally we should perform WOW resume only in the actual platform
2273 * resume path. This area needs bit rework to avoid WOW resume in RX path.
2274 *
2275 * ath6kl_check_wow_status() is called from ath6kl_rx().
2276 */
2277void ath6kl_check_wow_status(struct ath6kl *ar)
2278{
2279        if (ar->state == ATH6KL_STATE_SUSPENDING)
2280                return;
2281
2282        if (ar->state == ATH6KL_STATE_WOW)
2283                ath6kl_cfg80211_resume(ar);
2284}
2285
2286#else
2287
2288void ath6kl_check_wow_status(struct ath6kl *ar)
2289{
2290}
2291#endif
2292
2293static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
2294                              struct ieee80211_channel *chan,
2295                              enum nl80211_channel_type channel_type)
2296{
2297        struct ath6kl_vif *vif;
2298
2299        /*
2300         * 'dev' could be NULL if a channel change is required for the hardware
2301         * device itself, instead of a particular VIF.
2302         *
2303         * FIXME: To be handled properly when monitor mode is supported.
2304         */
2305        if (!dev)
2306                return -EBUSY;
2307
2308        vif = netdev_priv(dev);
2309
2310        if (!ath6kl_cfg80211_ready(vif))
2311                return -EIO;
2312
2313        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
2314                   __func__, chan->center_freq, chan->hw_value);
2315        vif->next_chan = chan->center_freq;
2316
2317        return 0;
2318}
2319
2320static bool ath6kl_is_p2p_ie(const u8 *pos)
2321{
2322        return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
2323                pos[2] == 0x50 && pos[3] == 0x6f &&
2324                pos[4] == 0x9a && pos[5] == 0x09;
2325}
2326
2327static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
2328                                        const u8 *ies, size_t ies_len)
2329{
2330        struct ath6kl *ar = vif->ar;
2331        const u8 *pos;
2332        u8 *buf = NULL;
2333        size_t len = 0;
2334        int ret;
2335
2336        /*
2337         * Filter out P2P IE(s) since they will be included depending on
2338         * the Probe Request frame in ath6kl_send_go_probe_resp().
2339         */
2340
2341        if (ies && ies_len) {
2342                buf = kmalloc(ies_len, GFP_KERNEL);
2343                if (buf == NULL)
2344                        return -ENOMEM;
2345                pos = ies;
2346                while (pos + 1 < ies + ies_len) {
2347                        if (pos + 2 + pos[1] > ies + ies_len)
2348                                break;
2349                        if (!ath6kl_is_p2p_ie(pos)) {
2350                                memcpy(buf + len, pos, 2 + pos[1]);
2351                                len += 2 + pos[1];
2352                        }
2353                        pos += 2 + pos[1];
2354                }
2355        }
2356
2357        ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2358                                       WMI_FRAME_PROBE_RESP, buf, len);
2359        kfree(buf);
2360        return ret;
2361}
2362
2363static int ath6kl_set_ies(struct ath6kl_vif *vif,
2364                          struct cfg80211_beacon_data *info)
2365{
2366        struct ath6kl *ar = vif->ar;
2367        int res;
2368
2369        /* this also clears IE in fw if it's not set */
2370        res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2371                                       WMI_FRAME_BEACON,
2372                                       info->beacon_ies,
2373                                       info->beacon_ies_len);
2374        if (res)
2375                return res;
2376
2377        /* this also clears IE in fw if it's not set */
2378        res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
2379                                           info->proberesp_ies_len);
2380        if (res)
2381                return res;
2382
2383        /* this also clears IE in fw if it's not set */
2384        res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2385                                       WMI_FRAME_ASSOC_RESP,
2386                                       info->assocresp_ies,
2387                                       info->assocresp_ies_len);
2388        if (res)
2389                return res;
2390
2391        return 0;
2392}
2393
2394static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2395                           struct cfg80211_ap_settings *info)
2396{
2397        struct ath6kl *ar = ath6kl_priv(dev);
2398        struct ath6kl_vif *vif = netdev_priv(dev);
2399        struct ieee80211_mgmt *mgmt;
2400        bool hidden = false;
2401        u8 *ies;
2402        int ies_len;
2403        struct wmi_connect_cmd p;
2404        int res;
2405        int i, ret;
2406
2407        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
2408
2409        if (!ath6kl_cfg80211_ready(vif))
2410                return -EIO;
2411
2412        if (vif->next_mode != AP_NETWORK)
2413                return -EOPNOTSUPP;
2414
2415        res = ath6kl_set_ies(vif, &info->beacon);
2416
2417        ar->ap_mode_bkey.valid = false;
2418
2419        /* TODO:
2420         * info->interval
2421         * info->dtim_period
2422         */
2423
2424        if (info->beacon.head == NULL)
2425                return -EINVAL;
2426        mgmt = (struct ieee80211_mgmt *) info->beacon.head;
2427        ies = mgmt->u.beacon.variable;
2428        if (ies > info->beacon.head + info->beacon.head_len)
2429                return -EINVAL;
2430        ies_len = info->beacon.head + info->beacon.head_len - ies;
2431
2432        if (info->ssid == NULL)
2433                return -EINVAL;
2434        memcpy(vif->ssid, info->ssid, info->ssid_len);
2435        vif->ssid_len = info->ssid_len;
2436        if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2437                hidden = true;
2438
2439        res = ath6kl_wmi_ap_hidden_ssid(ar->wmi, vif->fw_vif_idx, hidden);
2440        if (res)
2441                return res;
2442
2443        ret = ath6kl_set_auth_type(vif, info->auth_type);
2444        if (ret)
2445                return ret;
2446
2447        memset(&p, 0, sizeof(p));
2448
2449        for (i = 0; i < info->crypto.n_akm_suites; i++) {
2450                switch (info->crypto.akm_suites[i]) {
2451                case WLAN_AKM_SUITE_8021X:
2452                        if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2453                                p.auth_mode |= WPA_AUTH;
2454                        if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2455                                p.auth_mode |= WPA2_AUTH;
2456                        break;
2457                case WLAN_AKM_SUITE_PSK:
2458                        if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2459                                p.auth_mode |= WPA_PSK_AUTH;
2460                        if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2461                                p.auth_mode |= WPA2_PSK_AUTH;
2462                        break;
2463                }
2464        }
2465        if (p.auth_mode == 0)
2466                p.auth_mode = NONE_AUTH;
2467        vif->auth_mode = p.auth_mode;
2468
2469        for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
2470                switch (info->crypto.ciphers_pairwise[i]) {
2471                case WLAN_CIPHER_SUITE_WEP40:
2472                case WLAN_CIPHER_SUITE_WEP104:
2473                        p.prwise_crypto_type |= WEP_CRYPT;
2474                        break;
2475                case WLAN_CIPHER_SUITE_TKIP:
2476                        p.prwise_crypto_type |= TKIP_CRYPT;
2477                        break;
2478                case WLAN_CIPHER_SUITE_CCMP:
2479                        p.prwise_crypto_type |= AES_CRYPT;
2480                        break;
2481                case WLAN_CIPHER_SUITE_SMS4:
2482                        p.prwise_crypto_type |= WAPI_CRYPT;
2483                        break;
2484                }
2485        }
2486        if (p.prwise_crypto_type == 0) {
2487                p.prwise_crypto_type = NONE_CRYPT;
2488                ath6kl_set_cipher(vif, 0, true);
2489        } else if (info->crypto.n_ciphers_pairwise == 1)
2490                ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
2491
2492        switch (info->crypto.cipher_group) {
2493        case WLAN_CIPHER_SUITE_WEP40:
2494        case WLAN_CIPHER_SUITE_WEP104:
2495                p.grp_crypto_type = WEP_CRYPT;
2496                break;
2497        case WLAN_CIPHER_SUITE_TKIP:
2498                p.grp_crypto_type = TKIP_CRYPT;
2499                break;
2500        case WLAN_CIPHER_SUITE_CCMP:
2501                p.grp_crypto_type = AES_CRYPT;
2502                break;
2503        case WLAN_CIPHER_SUITE_SMS4:
2504                p.grp_crypto_type = WAPI_CRYPT;
2505                break;
2506        default:
2507                p.grp_crypto_type = NONE_CRYPT;
2508                break;
2509        }
2510        ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
2511
2512        p.nw_type = AP_NETWORK;
2513        vif->nw_type = vif->next_mode;
2514
2515        p.ssid_len = vif->ssid_len;
2516        memcpy(p.ssid, vif->ssid, vif->ssid_len);
2517        p.dot11_auth_mode = vif->dot11_auth_mode;
2518        p.ch = cpu_to_le16(vif->next_chan);
2519
2520        /* Enable uAPSD support by default */
2521        res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
2522        if (res < 0)
2523                return res;
2524
2525        if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
2526                p.nw_subtype = SUBTYPE_P2PGO;
2527        } else {
2528                /*
2529                 * Due to firmware limitation, it is not possible to
2530                 * do P2P mgmt operations in AP mode
2531                 */
2532                p.nw_subtype = SUBTYPE_NONE;
2533        }
2534
2535        res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
2536        if (res < 0)
2537                return res;
2538
2539        return 0;
2540}
2541
2542static int ath6kl_change_beacon(struct wiphy *wiphy, struct net_device *dev,
2543                                struct cfg80211_beacon_data *beacon)
2544{
2545        struct ath6kl_vif *vif = netdev_priv(dev);
2546
2547        if (!ath6kl_cfg80211_ready(vif))
2548                return -EIO;
2549
2550        if (vif->next_mode != AP_NETWORK)
2551                return -EOPNOTSUPP;
2552
2553        return ath6kl_set_ies(vif, beacon);
2554}
2555
2556static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
2557{
2558        struct ath6kl *ar = ath6kl_priv(dev);
2559        struct ath6kl_vif *vif = netdev_priv(dev);
2560
2561        if (vif->nw_type != AP_NETWORK)
2562                return -EOPNOTSUPP;
2563        if (!test_bit(CONNECTED, &vif->flags))
2564                return -ENOTCONN;
2565
2566        ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
2567        clear_bit(CONNECTED, &vif->flags);
2568
2569        return 0;
2570}
2571
2572static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2573
2574static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
2575                              u8 *mac)
2576{
2577        struct ath6kl *ar = ath6kl_priv(dev);
2578        struct ath6kl_vif *vif = netdev_priv(dev);
2579        const u8 *addr = mac ? mac : bcast_addr;
2580
2581        return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH,
2582                                      addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
2583}
2584
2585static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
2586                                 u8 *mac, struct station_parameters *params)
2587{
2588        struct ath6kl *ar = ath6kl_priv(dev);
2589        struct ath6kl_vif *vif = netdev_priv(dev);
2590
2591        if (vif->nw_type != AP_NETWORK)
2592                return -EOPNOTSUPP;
2593
2594        /* Use this only for authorizing/unauthorizing a station */
2595        if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
2596                return -EOPNOTSUPP;
2597
2598        if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2599                return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2600                                              WMI_AP_MLME_AUTHORIZE, mac, 0);
2601        return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2602                                      WMI_AP_MLME_UNAUTHORIZE, mac, 0);
2603}
2604
2605static int ath6kl_remain_on_channel(struct wiphy *wiphy,
2606                                    struct net_device *dev,
2607                                    struct ieee80211_channel *chan,
2608                                    enum nl80211_channel_type channel_type,
2609                                    unsigned int duration,
2610                                    u64 *cookie)
2611{
2612        struct ath6kl *ar = ath6kl_priv(dev);
2613        struct ath6kl_vif *vif = netdev_priv(dev);
2614        u32 id;
2615
2616        /* TODO: if already pending or ongoing remain-on-channel,
2617         * return -EBUSY */
2618        id = ++vif->last_roc_id;
2619        if (id == 0) {
2620                /* Do not use 0 as the cookie value */
2621                id = ++vif->last_roc_id;
2622        }
2623        *cookie = id;
2624
2625        return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
2626                                             chan->center_freq, duration);
2627}
2628
2629static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
2630                                           struct net_device *dev,
2631                                           u64 cookie)
2632{
2633        struct ath6kl *ar = ath6kl_priv(dev);
2634        struct ath6kl_vif *vif = netdev_priv(dev);
2635
2636        if (cookie != vif->last_roc_id)
2637                return -ENOENT;
2638        vif->last_cancel_roc_id = cookie;
2639
2640        return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
2641}
2642
2643static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
2644                                     const u8 *buf, size_t len,
2645                                     unsigned int freq)
2646{
2647        struct ath6kl *ar = vif->ar;
2648        const u8 *pos;
2649        u8 *p2p;
2650        int p2p_len;
2651        int ret;
2652        const struct ieee80211_mgmt *mgmt;
2653
2654        mgmt = (const struct ieee80211_mgmt *) buf;
2655
2656        /* Include P2P IE(s) from the frame generated in user space. */
2657
2658        p2p = kmalloc(len, GFP_KERNEL);
2659        if (p2p == NULL)
2660                return -ENOMEM;
2661        p2p_len = 0;
2662
2663        pos = mgmt->u.probe_resp.variable;
2664        while (pos + 1 < buf + len) {
2665                if (pos + 2 + pos[1] > buf + len)
2666                        break;
2667                if (ath6kl_is_p2p_ie(pos)) {
2668                        memcpy(p2p + p2p_len, pos, 2 + pos[1]);
2669                        p2p_len += 2 + pos[1];
2670                }
2671                pos += 2 + pos[1];
2672        }
2673
2674        ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
2675                                                 mgmt->da, p2p, p2p_len);
2676        kfree(p2p);
2677        return ret;
2678}
2679
2680static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
2681                                     u32 id,
2682                                     u32 freq,
2683                                     u32 wait,
2684                                     const u8 *buf,
2685                                     size_t len,
2686                                     bool *more_data,
2687                                     bool no_cck)
2688{
2689        struct ieee80211_mgmt *mgmt;
2690        struct ath6kl_sta *conn;
2691        bool is_psq_empty = false;
2692        struct ath6kl_mgmt_buff *mgmt_buf;
2693        size_t mgmt_buf_size;
2694        struct ath6kl *ar = vif->ar;
2695
2696        mgmt = (struct ieee80211_mgmt *) buf;
2697        if (is_multicast_ether_addr(mgmt->da))
2698                return false;
2699
2700        conn = ath6kl_find_sta(vif, mgmt->da);
2701        if (!conn)
2702                return false;
2703
2704        if (conn->sta_flags & STA_PS_SLEEP) {
2705                if (!(conn->sta_flags & STA_PS_POLLED)) {
2706                        /* Queue the frames if the STA is sleeping */
2707                        mgmt_buf_size = len + sizeof(struct ath6kl_mgmt_buff);
2708                        mgmt_buf = kmalloc(mgmt_buf_size, GFP_KERNEL);
2709                        if (!mgmt_buf)
2710                                return false;
2711
2712                        INIT_LIST_HEAD(&mgmt_buf->list);
2713                        mgmt_buf->id = id;
2714                        mgmt_buf->freq = freq;
2715                        mgmt_buf->wait = wait;
2716                        mgmt_buf->len = len;
2717                        mgmt_buf->no_cck = no_cck;
2718                        memcpy(mgmt_buf->buf, buf, len);
2719                        spin_lock_bh(&conn->psq_lock);
2720                        is_psq_empty = skb_queue_empty(&conn->psq) &&
2721                                        (conn->mgmt_psq_len == 0);
2722                        list_add_tail(&mgmt_buf->list, &conn->mgmt_psq);
2723                        conn->mgmt_psq_len++;
2724                        spin_unlock_bh(&conn->psq_lock);
2725
2726                        /*
2727                         * If this is the first pkt getting queued
2728                         * for this STA, update the PVB for this
2729                         * STA.
2730                         */
2731                        if (is_psq_empty)
2732                                ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
2733                                                       conn->aid, 1);
2734                        return true;
2735                }
2736
2737                /*
2738                 * This tx is because of a PsPoll.
2739                 * Determine if MoreData bit has to be set.
2740                 */
2741                spin_lock_bh(&conn->psq_lock);
2742                if (!skb_queue_empty(&conn->psq) || (conn->mgmt_psq_len != 0))
2743                        *more_data = true;
2744                spin_unlock_bh(&conn->psq_lock);
2745        }
2746
2747        return false;
2748}
2749
2750static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2751                          struct ieee80211_channel *chan, bool offchan,
2752                          enum nl80211_channel_type channel_type,
2753                          bool channel_type_valid, unsigned int wait,
2754                          const u8 *buf, size_t len, bool no_cck,
2755                          bool dont_wait_for_ack, u64 *cookie)
2756{
2757        struct ath6kl *ar = ath6kl_priv(dev);
2758        struct ath6kl_vif *vif = netdev_priv(dev);
2759        u32 id;
2760        const struct ieee80211_mgmt *mgmt;
2761        bool more_data, queued;
2762
2763        mgmt = (const struct ieee80211_mgmt *) buf;
2764        if (buf + len >= mgmt->u.probe_resp.variable &&
2765            vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
2766            ieee80211_is_probe_resp(mgmt->frame_control)) {
2767                /*
2768                 * Send Probe Response frame in AP mode using a separate WMI
2769                 * command to allow the target to fill in the generic IEs.
2770                 */
2771                *cookie = 0; /* TX status not supported */
2772                return ath6kl_send_go_probe_resp(vif, buf, len,
2773                                                 chan->center_freq);
2774        }
2775
2776        id = vif->send_action_id++;
2777        if (id == 0) {
2778                /*
2779                 * 0 is a reserved value in the WMI command and shall not be
2780                 * used for the command.
2781                 */
2782                id = vif->send_action_id++;
2783        }
2784
2785        *cookie = id;
2786
2787        /* AP mode Power saving processing */
2788        if (vif->nw_type == AP_NETWORK) {
2789                queued = ath6kl_mgmt_powersave_ap(vif,
2790                                        id, chan->center_freq,
2791                                        wait, buf,
2792                                        len, &more_data, no_cck);
2793                if (queued)
2794                        return 0;
2795        }
2796
2797        return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2798                                        chan->center_freq, wait,
2799                                        buf, len, no_cck);
2800}
2801
2802static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
2803                                       struct net_device *dev,
2804                                       u16 frame_type, bool reg)
2805{
2806        struct ath6kl_vif *vif = netdev_priv(dev);
2807
2808        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
2809                   __func__, frame_type, reg);
2810        if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
2811                /*
2812                 * Note: This notification callback is not allowed to sleep, so
2813                 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
2814                 * hardcode target to report Probe Request frames all the time.
2815                 */
2816                vif->probe_req_report = reg;
2817        }
2818}
2819
2820static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
2821                        struct net_device *dev,
2822                        struct cfg80211_sched_scan_request *request)
2823{
2824        struct ath6kl *ar = ath6kl_priv(dev);
2825        struct ath6kl_vif *vif = netdev_priv(dev);
2826        u16 interval;
2827        int ret;
2828        u8 i;
2829
2830        if (ar->state != ATH6KL_STATE_ON)
2831                return -EIO;
2832
2833        if (vif->sme_state != SME_DISCONNECTED)
2834                return -EBUSY;
2835
2836        for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
2837                ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2838                                          i, DISABLE_SSID_FLAG,
2839                                          0, NULL);
2840        }
2841
2842        /* fw uses seconds, also make sure that it's >0 */
2843        interval = max_t(u16, 1, request->interval / 1000);
2844
2845        ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2846                                  interval, interval,
2847                                  10, 0, 0, 0, 3, 0, 0, 0);
2848
2849        if (request->n_ssids && request->ssids[0].ssid_len) {
2850                for (i = 0; i < request->n_ssids; i++) {
2851                        ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2852                                                  i, SPECIFIC_SSID_FLAG,
2853                                                  request->ssids[i].ssid_len,
2854                                                  request->ssids[i].ssid);
2855                }
2856        }
2857
2858        ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2859                                          ATH6KL_WOW_MODE_ENABLE,
2860                                          WOW_FILTER_SSID,
2861                                          WOW_HOST_REQ_DELAY);
2862        if (ret) {
2863                ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
2864                return ret;
2865        }
2866
2867        /* this also clears IE in fw if it's not set */
2868        ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2869                                       WMI_FRAME_PROBE_REQ,
2870                                       request->ie, request->ie_len);
2871        if (ret) {
2872                ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
2873                            ret);
2874                return ret;
2875        }
2876
2877        ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2878                                                 ATH6KL_HOST_MODE_ASLEEP);
2879        if (ret) {
2880                ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
2881                            ret);
2882                return ret;
2883        }
2884
2885        ar->state = ATH6KL_STATE_SCHED_SCAN;
2886
2887        return ret;
2888}
2889
2890static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
2891                                      struct net_device *dev)
2892{
2893        struct ath6kl_vif *vif = netdev_priv(dev);
2894        bool stopped;
2895
2896        stopped = __ath6kl_cfg80211_sscan_stop(vif);
2897
2898        if (!stopped)
2899                return -EIO;
2900
2901        return 0;
2902}
2903
2904static const struct ieee80211_txrx_stypes
2905ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
2906        [NL80211_IFTYPE_STATION] = {
2907                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2908                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2909                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2910                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2911        },
2912        [NL80211_IFTYPE_AP] = {
2913                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2914                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2915                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2916                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2917        },
2918        [NL80211_IFTYPE_P2P_CLIENT] = {
2919                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2920                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2921                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2922                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2923        },
2924        [NL80211_IFTYPE_P2P_GO] = {
2925                .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2926                BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2927                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2928                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2929        },
2930};
2931
2932static struct cfg80211_ops ath6kl_cfg80211_ops = {
2933        .add_virtual_intf = ath6kl_cfg80211_add_iface,
2934        .del_virtual_intf = ath6kl_cfg80211_del_iface,
2935        .change_virtual_intf = ath6kl_cfg80211_change_iface,
2936        .scan = ath6kl_cfg80211_scan,
2937        .connect = ath6kl_cfg80211_connect,
2938        .disconnect = ath6kl_cfg80211_disconnect,
2939        .add_key = ath6kl_cfg80211_add_key,
2940        .get_key = ath6kl_cfg80211_get_key,
2941        .del_key = ath6kl_cfg80211_del_key,
2942        .set_default_key = ath6kl_cfg80211_set_default_key,
2943        .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
2944        .set_tx_power = ath6kl_cfg80211_set_txpower,
2945        .get_tx_power = ath6kl_cfg80211_get_txpower,
2946        .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
2947        .join_ibss = ath6kl_cfg80211_join_ibss,
2948        .leave_ibss = ath6kl_cfg80211_leave_ibss,
2949        .get_station = ath6kl_get_station,
2950        .set_pmksa = ath6kl_set_pmksa,
2951        .del_pmksa = ath6kl_del_pmksa,
2952        .flush_pmksa = ath6kl_flush_pmksa,
2953        CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
2954#ifdef CONFIG_PM
2955        .suspend = __ath6kl_cfg80211_suspend,
2956        .resume = __ath6kl_cfg80211_resume,
2957#endif
2958        .set_channel = ath6kl_set_channel,
2959        .start_ap = ath6kl_start_ap,
2960        .change_beacon = ath6kl_change_beacon,
2961        .stop_ap = ath6kl_stop_ap,
2962        .del_station = ath6kl_del_station,
2963        .change_station = ath6kl_change_station,
2964        .remain_on_channel = ath6kl_remain_on_channel,
2965        .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
2966        .mgmt_tx = ath6kl_mgmt_tx,
2967        .mgmt_frame_register = ath6kl_mgmt_frame_register,
2968        .sched_scan_start = ath6kl_cfg80211_sscan_start,
2969        .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
2970};
2971
2972void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
2973{
2974        ath6kl_cfg80211_sscan_disable(vif);
2975
2976        switch (vif->sme_state) {
2977        case SME_DISCONNECTED:
2978                break;
2979        case SME_CONNECTING:
2980                cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
2981                                        NULL, 0,
2982                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
2983                                        GFP_KERNEL);
2984                break;
2985        case SME_CONNECTED:
2986                cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
2987                break;
2988        }
2989
2990        if (test_bit(CONNECTED, &vif->flags) ||
2991            test_bit(CONNECT_PEND, &vif->flags))
2992                ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
2993
2994        vif->sme_state = SME_DISCONNECTED;
2995        clear_bit(CONNECTED, &vif->flags);
2996        clear_bit(CONNECT_PEND, &vif->flags);
2997
2998        /* disable scanning */
2999        if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
3000                                      0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
3001                ath6kl_warn("failed to disable scan during stop\n");
3002
3003        ath6kl_cfg80211_scan_complete_event(vif, true);
3004}
3005
3006void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
3007{
3008        struct ath6kl_vif *vif;
3009
3010        vif = ath6kl_vif_first(ar);
3011        if (!vif) {
3012                /* save the current power mode before enabling power save */
3013                ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
3014
3015                if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
3016                        ath6kl_warn("ath6kl_deep_sleep_enable: "
3017                                    "wmi_powermode_cmd failed\n");
3018                return;
3019        }
3020
3021        /*
3022         * FIXME: we should take ar->list_lock to protect changes in the
3023         * vif_list, but that's not trivial to do as ath6kl_cfg80211_stop()
3024         * sleeps.
3025         */
3026        list_for_each_entry(vif, &ar->vif_list, list)
3027                ath6kl_cfg80211_stop(vif);
3028}
3029
3030static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
3031{
3032        vif->aggr_cntxt = aggr_init(vif);
3033        if (!vif->aggr_cntxt) {
3034                ath6kl_err("failed to initialize aggr\n");
3035                return -ENOMEM;
3036        }
3037
3038        setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
3039                    (unsigned long) vif->ndev);
3040        setup_timer(&vif->sched_scan_timer, ath6kl_wmi_sscan_timer,
3041                    (unsigned long) vif);
3042
3043        set_bit(WMM_ENABLED, &vif->flags);
3044        spin_lock_init(&vif->if_lock);
3045
3046        INIT_LIST_HEAD(&vif->mc_filter);
3047
3048        return 0;
3049}
3050
3051void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
3052{
3053        struct ath6kl *ar = vif->ar;
3054        struct ath6kl_mc_filter *mc_filter, *tmp;
3055
3056        aggr_module_destroy(vif->aggr_cntxt);
3057
3058        ar->avail_idx_map |= BIT(vif->fw_vif_idx);
3059
3060        if (vif->nw_type == ADHOC_NETWORK)
3061                ar->ibss_if_active = false;
3062
3063        list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
3064                list_del(&mc_filter->list);
3065                kfree(mc_filter);
3066        }
3067
3068        unregister_netdevice(vif->ndev);
3069
3070        ar->num_vif--;
3071}
3072
3073struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
3074                                        enum nl80211_iftype type, u8 fw_vif_idx,
3075                                        u8 nw_type)
3076{
3077        struct net_device *ndev;
3078        struct ath6kl_vif *vif;
3079
3080        ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
3081        if (!ndev)
3082                return NULL;
3083
3084        vif = netdev_priv(ndev);
3085        ndev->ieee80211_ptr = &vif->wdev;
3086        vif->wdev.wiphy = ar->wiphy;
3087        vif->ar = ar;
3088        vif->ndev = ndev;
3089        SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
3090        vif->wdev.netdev = ndev;
3091        vif->wdev.iftype = type;
3092        vif->fw_vif_idx = fw_vif_idx;
3093        vif->nw_type = nw_type;
3094        vif->next_mode = nw_type;
3095        vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
3096        vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
3097
3098        memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
3099        if (fw_vif_idx != 0)
3100                ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
3101                                     0x2;
3102
3103        init_netdev(ndev);
3104
3105        ath6kl_init_control_info(vif);
3106
3107        if (ath6kl_cfg80211_vif_init(vif))
3108                goto err;
3109
3110        if (register_netdevice(ndev))
3111                goto err;
3112
3113        ar->avail_idx_map &= ~BIT(fw_vif_idx);
3114        vif->sme_state = SME_DISCONNECTED;
3115        set_bit(WLAN_ENABLED, &vif->flags);
3116        ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
3117        set_bit(NETDEV_REGISTERED, &vif->flags);
3118
3119        if (type == NL80211_IFTYPE_ADHOC)
3120                ar->ibss_if_active = true;
3121
3122        spin_lock_bh(&ar->list_lock);
3123        list_add_tail(&vif->list, &ar->vif_list);
3124        spin_unlock_bh(&ar->list_lock);
3125
3126        return ndev;
3127
3128err:
3129        aggr_module_destroy(vif->aggr_cntxt);
3130        free_netdev(ndev);
3131        return NULL;
3132}
3133
3134int ath6kl_cfg80211_init(struct ath6kl *ar)
3135{
3136        struct wiphy *wiphy = ar->wiphy;
3137        int ret;
3138
3139        wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
3140
3141        wiphy->max_remain_on_channel_duration = 5000;
3142
3143        /* set device pointer for wiphy */
3144        set_wiphy_dev(wiphy, ar->dev);
3145
3146        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3147                                 BIT(NL80211_IFTYPE_ADHOC) |
3148                                 BIT(NL80211_IFTYPE_AP);
3149        if (ar->p2p) {
3150                wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
3151                                          BIT(NL80211_IFTYPE_P2P_CLIENT);
3152        }
3153
3154        /* max num of ssids that can be probed during scanning */
3155        wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
3156        wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
3157        wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
3158        wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
3159        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3160
3161        wiphy->cipher_suites = cipher_suites;
3162        wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
3163
3164        wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
3165                              WIPHY_WOWLAN_DISCONNECT |
3166                              WIPHY_WOWLAN_GTK_REKEY_FAILURE  |
3167                              WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
3168                              WIPHY_WOWLAN_EAP_IDENTITY_REQ   |
3169                              WIPHY_WOWLAN_4WAY_HANDSHAKE;
3170        wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
3171        wiphy->wowlan.pattern_min_len = 1;
3172        wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
3173
3174        wiphy->max_sched_scan_ssids = 10;
3175
3176        ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
3177                            WIPHY_FLAG_HAVE_AP_SME |
3178                            WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3179                            WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
3180
3181        if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
3182                ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3183
3184        ar->wiphy->probe_resp_offload =
3185                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
3186                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
3187                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
3188                NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
3189
3190        ret = wiphy_register(wiphy);
3191        if (ret < 0) {
3192                ath6kl_err("couldn't register wiphy device\n");
3193                return ret;
3194        }
3195
3196        ar->wiphy_registered = true;
3197
3198        return 0;
3199}
3200
3201void ath6kl_cfg80211_cleanup(struct ath6kl *ar)
3202{
3203        wiphy_unregister(ar->wiphy);
3204
3205        ar->wiphy_registered = false;
3206}
3207
3208struct ath6kl *ath6kl_cfg80211_create(void)
3209{
3210        struct ath6kl *ar;
3211        struct wiphy *wiphy;
3212
3213        /* create a new wiphy for use with cfg80211 */
3214        wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
3215
3216        if (!wiphy) {
3217                ath6kl_err("couldn't allocate wiphy device\n");
3218                return NULL;
3219        }
3220
3221        ar = wiphy_priv(wiphy);
3222        ar->wiphy = wiphy;
3223
3224        return ar;
3225}
3226
3227/* Note: ar variable must not be accessed after calling this! */
3228void ath6kl_cfg80211_destroy(struct ath6kl *ar)
3229{
3230        int i;
3231
3232        for (i = 0; i < AP_MAX_NUM_STA; i++)
3233                kfree(ar->sta_list[i].aggr_conn);
3234
3235        wiphy_free(ar->wiphy);
3236}
3237
3238