linux/drivers/net/wireless/iwmc3200wifi/cfg80211.c
<<
>>
Prefs
   1/*
   2 * Intel Wireless Multicomm 3200 WiFi driver
   3 *
   4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
   5 * Samuel Ortiz <samuel.ortiz@intel.com>
   6 * Zhu Yi <yi.zhu@intel.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License version
  10 * 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20 * 02110-1301, USA.
  21 *
  22 */
  23
  24#include <linux/kernel.h>
  25#include <linux/netdevice.h>
  26#include <linux/sched.h>
  27#include <linux/etherdevice.h>
  28#include <linux/wireless.h>
  29#include <linux/ieee80211.h>
  30#include <linux/slab.h>
  31#include <net/cfg80211.h>
  32
  33#include "iwm.h"
  34#include "commands.h"
  35#include "cfg80211.h"
  36#include "debug.h"
  37
  38#define RATETAB_ENT(_rate, _rateid, _flags) \
  39        {                                                               \
  40                .bitrate        = (_rate),                              \
  41                .hw_value       = (_rateid),                            \
  42                .flags          = (_flags),                             \
  43        }
  44
  45#define CHAN2G(_channel, _freq, _flags) {                       \
  46        .band                   = IEEE80211_BAND_2GHZ,          \
  47        .center_freq            = (_freq),                      \
  48        .hw_value               = (_channel),                   \
  49        .flags                  = (_flags),                     \
  50        .max_antenna_gain       = 0,                            \
  51        .max_power              = 30,                           \
  52}
  53
  54#define CHAN5G(_channel, _flags) {                              \
  55        .band                   = IEEE80211_BAND_5GHZ,          \
  56        .center_freq            = 5000 + (5 * (_channel)),      \
  57        .hw_value               = (_channel),                   \
  58        .flags                  = (_flags),                     \
  59        .max_antenna_gain       = 0,                            \
  60        .max_power              = 30,                           \
  61}
  62
  63static struct ieee80211_rate iwm_rates[] = {
  64        RATETAB_ENT(10,  0x1,   0),
  65        RATETAB_ENT(20,  0x2,   0),
  66        RATETAB_ENT(55,  0x4,   0),
  67        RATETAB_ENT(110, 0x8,   0),
  68        RATETAB_ENT(60,  0x10,  0),
  69        RATETAB_ENT(90,  0x20,  0),
  70        RATETAB_ENT(120, 0x40,  0),
  71        RATETAB_ENT(180, 0x80,  0),
  72        RATETAB_ENT(240, 0x100, 0),
  73        RATETAB_ENT(360, 0x200, 0),
  74        RATETAB_ENT(480, 0x400, 0),
  75        RATETAB_ENT(540, 0x800, 0),
  76};
  77
  78#define iwm_a_rates             (iwm_rates + 4)
  79#define iwm_a_rates_size        8
  80#define iwm_g_rates             (iwm_rates + 0)
  81#define iwm_g_rates_size        12
  82
  83static struct ieee80211_channel iwm_2ghz_channels[] = {
  84        CHAN2G(1, 2412, 0),
  85        CHAN2G(2, 2417, 0),
  86        CHAN2G(3, 2422, 0),
  87        CHAN2G(4, 2427, 0),
  88        CHAN2G(5, 2432, 0),
  89        CHAN2G(6, 2437, 0),
  90        CHAN2G(7, 2442, 0),
  91        CHAN2G(8, 2447, 0),
  92        CHAN2G(9, 2452, 0),
  93        CHAN2G(10, 2457, 0),
  94        CHAN2G(11, 2462, 0),
  95        CHAN2G(12, 2467, 0),
  96        CHAN2G(13, 2472, 0),
  97        CHAN2G(14, 2484, 0),
  98};
  99
 100static struct ieee80211_channel iwm_5ghz_a_channels[] = {
 101        CHAN5G(34, 0),          CHAN5G(36, 0),
 102        CHAN5G(38, 0),          CHAN5G(40, 0),
 103        CHAN5G(42, 0),          CHAN5G(44, 0),
 104        CHAN5G(46, 0),          CHAN5G(48, 0),
 105        CHAN5G(52, 0),          CHAN5G(56, 0),
 106        CHAN5G(60, 0),          CHAN5G(64, 0),
 107        CHAN5G(100, 0),         CHAN5G(104, 0),
 108        CHAN5G(108, 0),         CHAN5G(112, 0),
 109        CHAN5G(116, 0),         CHAN5G(120, 0),
 110        CHAN5G(124, 0),         CHAN5G(128, 0),
 111        CHAN5G(132, 0),         CHAN5G(136, 0),
 112        CHAN5G(140, 0),         CHAN5G(149, 0),
 113        CHAN5G(153, 0),         CHAN5G(157, 0),
 114        CHAN5G(161, 0),         CHAN5G(165, 0),
 115        CHAN5G(184, 0),         CHAN5G(188, 0),
 116        CHAN5G(192, 0),         CHAN5G(196, 0),
 117        CHAN5G(200, 0),         CHAN5G(204, 0),
 118        CHAN5G(208, 0),         CHAN5G(212, 0),
 119        CHAN5G(216, 0),
 120};
 121
 122static struct ieee80211_supported_band iwm_band_2ghz = {
 123        .channels = iwm_2ghz_channels,
 124        .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
 125        .bitrates = iwm_g_rates,
 126        .n_bitrates = iwm_g_rates_size,
 127};
 128
 129static struct ieee80211_supported_band iwm_band_5ghz = {
 130        .channels = iwm_5ghz_a_channels,
 131        .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
 132        .bitrates = iwm_a_rates,
 133        .n_bitrates = iwm_a_rates_size,
 134};
 135
 136static int iwm_key_init(struct iwm_key *key, u8 key_index,
 137                        const u8 *mac_addr, struct key_params *params)
 138{
 139        key->hdr.key_idx = key_index;
 140        if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
 141                key->hdr.multicast = 1;
 142                memset(key->hdr.mac, 0xff, ETH_ALEN);
 143        } else {
 144                key->hdr.multicast = 0;
 145                memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
 146        }
 147
 148        if (params) {
 149                if (params->key_len > WLAN_MAX_KEY_LEN ||
 150                    params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
 151                        return -EINVAL;
 152
 153                key->cipher = params->cipher;
 154                key->key_len = params->key_len;
 155                key->seq_len = params->seq_len;
 156                memcpy(key->key, params->key, key->key_len);
 157                memcpy(key->seq, params->seq, key->seq_len);
 158        }
 159
 160        return 0;
 161}
 162
 163static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 164                                u8 key_index, bool pairwise, const u8 *mac_addr,
 165                                struct key_params *params)
 166{
 167        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 168        struct iwm_key *key = &iwm->keys[key_index];
 169        int ret;
 170
 171        IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
 172
 173        memset(key, 0, sizeof(struct iwm_key));
 174        ret = iwm_key_init(key, key_index, mac_addr, params);
 175        if (ret < 0) {
 176                IWM_ERR(iwm, "Invalid key_params\n");
 177                return ret;
 178        }
 179
 180        return iwm_set_key(iwm, 0, key);
 181}
 182
 183static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
 184                                u8 key_index, bool pairwise, const u8 *mac_addr,
 185                                void *cookie,
 186                                void (*callback)(void *cookie,
 187                                                 struct key_params*))
 188{
 189        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 190        struct iwm_key *key = &iwm->keys[key_index];
 191        struct key_params params;
 192
 193        IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
 194
 195        memset(&params, 0, sizeof(params));
 196
 197        params.cipher = key->cipher;
 198        params.key_len = key->key_len;
 199        params.seq_len = key->seq_len;
 200        params.seq = key->seq;
 201        params.key = key->key;
 202
 203        callback(cookie, &params);
 204
 205        return key->key_len ? 0 : -ENOENT;
 206}
 207
 208
 209static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 210                                u8 key_index, bool pairwise, const u8 *mac_addr)
 211{
 212        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 213        struct iwm_key *key = &iwm->keys[key_index];
 214
 215        if (!iwm->keys[key_index].key_len) {
 216                IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
 217                return 0;
 218        }
 219
 220        if (key_index == iwm->default_key)
 221                iwm->default_key = -1;
 222
 223        return iwm_set_key(iwm, 1, key);
 224}
 225
 226static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
 227                                        struct net_device *ndev,
 228                                        u8 key_index, bool unicast,
 229                                        bool multicast)
 230{
 231        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 232
 233        IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
 234
 235        if (!iwm->keys[key_index].key_len) {
 236                IWM_ERR(iwm, "Key %d not used\n", key_index);
 237                return -EINVAL;
 238        }
 239
 240        iwm->default_key = key_index;
 241
 242        return iwm_set_tx_key(iwm, key_index);
 243}
 244
 245static int iwm_cfg80211_get_station(struct wiphy *wiphy,
 246                                    struct net_device *ndev,
 247                                    u8 *mac, struct station_info *sinfo)
 248{
 249        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 250
 251        if (memcmp(mac, iwm->bssid, ETH_ALEN))
 252                return -ENOENT;
 253
 254        sinfo->filled |= STATION_INFO_TX_BITRATE;
 255        sinfo->txrate.legacy = iwm->rate * 10;
 256
 257        if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
 258                sinfo->filled |= STATION_INFO_SIGNAL;
 259                sinfo->signal = iwm->wstats.qual.level;
 260        }
 261
 262        return 0;
 263}
 264
 265
 266int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
 267{
 268        struct wiphy *wiphy = iwm_to_wiphy(iwm);
 269        struct iwm_bss_info *bss;
 270        struct iwm_umac_notif_bss_info *umac_bss;
 271        struct ieee80211_mgmt *mgmt;
 272        struct ieee80211_channel *channel;
 273        struct ieee80211_supported_band *band;
 274        s32 signal;
 275        int freq;
 276
 277        list_for_each_entry(bss, &iwm->bss_list, node) {
 278                umac_bss = bss->bss;
 279                mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
 280
 281                if (umac_bss->band == UMAC_BAND_2GHZ)
 282                        band = wiphy->bands[IEEE80211_BAND_2GHZ];
 283                else if (umac_bss->band == UMAC_BAND_5GHZ)
 284                        band = wiphy->bands[IEEE80211_BAND_5GHZ];
 285                else {
 286                        IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
 287                        return -EINVAL;
 288                }
 289
 290                freq = ieee80211_channel_to_frequency(umac_bss->channel,
 291                                                      band->band);
 292                channel = ieee80211_get_channel(wiphy, freq);
 293                signal = umac_bss->rssi * 100;
 294
 295                if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
 296                                               le16_to_cpu(umac_bss->frame_len),
 297                                               signal, GFP_KERNEL))
 298                        return -EINVAL;
 299        }
 300
 301        return 0;
 302}
 303
 304static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
 305                                     struct net_device *ndev,
 306                                     enum nl80211_iftype type, u32 *flags,
 307                                     struct vif_params *params)
 308{
 309        struct wireless_dev *wdev;
 310        struct iwm_priv *iwm;
 311        u32 old_mode;
 312
 313        wdev = ndev->ieee80211_ptr;
 314        iwm = ndev_to_iwm(ndev);
 315        old_mode = iwm->conf.mode;
 316
 317        switch (type) {
 318        case NL80211_IFTYPE_STATION:
 319                iwm->conf.mode = UMAC_MODE_BSS;
 320                break;
 321        case NL80211_IFTYPE_ADHOC:
 322                iwm->conf.mode = UMAC_MODE_IBSS;
 323                break;
 324        default:
 325                return -EOPNOTSUPP;
 326        }
 327
 328        wdev->iftype = type;
 329
 330        if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
 331                return 0;
 332
 333        iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
 334
 335        if (iwm->umac_profile_active)
 336                iwm_invalidate_mlme_profile(iwm);
 337
 338        return 0;
 339}
 340
 341static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 342                             struct cfg80211_scan_request *request)
 343{
 344        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 345        int ret;
 346
 347        if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
 348                IWM_ERR(iwm, "Scan while device is not ready\n");
 349                return -EIO;
 350        }
 351
 352        if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
 353                IWM_ERR(iwm, "Scanning already\n");
 354                return -EAGAIN;
 355        }
 356
 357        if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
 358                IWM_ERR(iwm, "Scanning being aborted\n");
 359                return -EAGAIN;
 360        }
 361
 362        set_bit(IWM_STATUS_SCANNING, &iwm->status);
 363
 364        ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
 365        if (ret) {
 366                clear_bit(IWM_STATUS_SCANNING, &iwm->status);
 367                return ret;
 368        }
 369
 370        iwm->scan_request = request;
 371        return 0;
 372}
 373
 374static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 375{
 376        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 377
 378        if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
 379            (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
 380                int ret;
 381
 382                iwm->conf.rts_threshold = wiphy->rts_threshold;
 383
 384                ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
 385                                             CFG_RTS_THRESHOLD,
 386                                             iwm->conf.rts_threshold);
 387                if (ret < 0)
 388                        return ret;
 389        }
 390
 391        if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
 392            (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
 393                int ret;
 394
 395                iwm->conf.frag_threshold = wiphy->frag_threshold;
 396
 397                ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
 398                                             CFG_FRAG_THRESHOLD,
 399                                             iwm->conf.frag_threshold);
 400                if (ret < 0)
 401                        return ret;
 402        }
 403
 404        return 0;
 405}
 406
 407static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 408                                  struct cfg80211_ibss_params *params)
 409{
 410        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 411        struct ieee80211_channel *chan = params->channel;
 412
 413        if (!test_bit(IWM_STATUS_READY, &iwm->status))
 414                return -EIO;
 415
 416        /* UMAC doesn't support creating or joining an IBSS network
 417         * with specified bssid. */
 418        if (params->bssid)
 419                return -EOPNOTSUPP;
 420
 421        iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
 422        iwm->umac_profile->ibss.band = chan->band;
 423        iwm->umac_profile->ibss.channel = iwm->channel;
 424        iwm->umac_profile->ssid.ssid_len = params->ssid_len;
 425        memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
 426
 427        return iwm_send_mlme_profile(iwm);
 428}
 429
 430static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 431{
 432        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 433
 434        if (iwm->umac_profile_active)
 435                return iwm_invalidate_mlme_profile(iwm);
 436
 437        return 0;
 438}
 439
 440static int iwm_set_auth_type(struct iwm_priv *iwm,
 441                             enum nl80211_auth_type sme_auth_type)
 442{
 443        u8 *auth_type = &iwm->umac_profile->sec.auth_type;
 444
 445        switch (sme_auth_type) {
 446        case NL80211_AUTHTYPE_AUTOMATIC:
 447        case NL80211_AUTHTYPE_OPEN_SYSTEM:
 448                IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
 449                *auth_type = UMAC_AUTH_TYPE_OPEN;
 450                break;
 451        case NL80211_AUTHTYPE_SHARED_KEY:
 452                if (iwm->umac_profile->sec.flags &
 453                    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
 454                        IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
 455                        *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
 456                } else {
 457                        IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
 458                        *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
 459                }
 460
 461                break;
 462        default:
 463                IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
 464                return -ENOTSUPP;
 465        }
 466
 467        return 0;
 468}
 469
 470static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
 471{
 472        IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
 473
 474        if (!wpa_version) {
 475                iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
 476                return 0;
 477        }
 478
 479        if (wpa_version & NL80211_WPA_VERSION_1)
 480                iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
 481
 482        if (wpa_version & NL80211_WPA_VERSION_2)
 483                iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
 484
 485        return 0;
 486}
 487
 488static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
 489{
 490        u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
 491                &iwm->umac_profile->sec.mcast_cipher;
 492
 493        if (!cipher) {
 494                *profile_cipher = UMAC_CIPHER_TYPE_NONE;
 495                return 0;
 496        }
 497
 498        IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
 499                     cipher);
 500
 501        switch (cipher) {
 502        case IW_AUTH_CIPHER_NONE:
 503                *profile_cipher = UMAC_CIPHER_TYPE_NONE;
 504                break;
 505        case WLAN_CIPHER_SUITE_WEP40:
 506                *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
 507                break;
 508        case WLAN_CIPHER_SUITE_WEP104:
 509                *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
 510                break;
 511        case WLAN_CIPHER_SUITE_TKIP:
 512                *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
 513                break;
 514        case WLAN_CIPHER_SUITE_CCMP:
 515                *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
 516                break;
 517        default:
 518                IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
 519                return -ENOTSUPP;
 520        }
 521
 522        return 0;
 523}
 524
 525static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
 526{
 527        u8 *auth_type = &iwm->umac_profile->sec.auth_type;
 528
 529        IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
 530
 531        if (key_mgt == WLAN_AKM_SUITE_8021X)
 532                *auth_type = UMAC_AUTH_TYPE_8021X;
 533        else if (key_mgt == WLAN_AKM_SUITE_PSK) {
 534                if (iwm->umac_profile->sec.flags &
 535                    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
 536                        *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
 537                else
 538                        *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
 539        } else {
 540                IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
 541                return -EINVAL;
 542        }
 543
 544        return 0;
 545}
 546
 547
 548static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 549                                 struct cfg80211_connect_params *sme)
 550{
 551        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 552        struct ieee80211_channel *chan = sme->channel;
 553        struct key_params key_param;
 554        int ret;
 555
 556        if (!test_bit(IWM_STATUS_READY, &iwm->status))
 557                return -EIO;
 558
 559        if (!sme->ssid)
 560                return -EINVAL;
 561
 562        if (iwm->umac_profile_active) {
 563                ret = iwm_invalidate_mlme_profile(iwm);
 564                if (ret) {
 565                        IWM_ERR(iwm, "Couldn't invalidate profile\n");
 566                        return ret;
 567                }
 568        }
 569
 570        if (chan)
 571                iwm->channel =
 572                        ieee80211_frequency_to_channel(chan->center_freq);
 573
 574        iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
 575        memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
 576
 577        if (sme->bssid) {
 578                IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
 579                memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
 580                iwm->umac_profile->bss_num = 1;
 581        } else {
 582                memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
 583                iwm->umac_profile->bss_num = 0;
 584        }
 585
 586        ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
 587        if (ret < 0)
 588                return ret;
 589
 590        ret = iwm_set_auth_type(iwm, sme->auth_type);
 591        if (ret < 0)
 592                return ret;
 593
 594        if (sme->crypto.n_ciphers_pairwise) {
 595                ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
 596                                     true);
 597                if (ret < 0)
 598                        return ret;
 599        }
 600
 601        ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
 602        if (ret < 0)
 603                return ret;
 604
 605        if (sme->crypto.n_akm_suites) {
 606                ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
 607                if (ret < 0)
 608                        return ret;
 609        }
 610
 611        /*
 612         * We save the WEP key in case we want to do shared authentication.
 613         * We have to do it so because UMAC will assert whenever it gets a
 614         * key before a profile.
 615         */
 616        if (sme->key) {
 617                key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
 618                if (key_param.key == NULL)
 619                        return -ENOMEM;
 620                key_param.key_len = sme->key_len;
 621                key_param.seq_len = 0;
 622                key_param.cipher = sme->crypto.ciphers_pairwise[0];
 623
 624                ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
 625                                   NULL, &key_param);
 626                kfree(key_param.key);
 627                if (ret < 0) {
 628                        IWM_ERR(iwm, "Invalid key_params\n");
 629                        return ret;
 630                }
 631
 632                iwm->default_key = sme->key_idx;
 633        }
 634
 635        /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
 636        if ((iwm->umac_profile->sec.flags &
 637             (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
 638            iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
 639                        iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
 640        }
 641
 642        ret = iwm_send_mlme_profile(iwm);
 643
 644        if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
 645            sme->key == NULL)
 646                return ret;
 647
 648        /*
 649         * We want to do shared auth.
 650         * We need to actually set the key we previously cached,
 651         * and then tell the UMAC it's the default one.
 652         * That will trigger the auth+assoc UMAC machinery, and again,
 653         * this must be done after setting the profile.
 654         */
 655        ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
 656        if (ret < 0)
 657                return ret;
 658
 659        return iwm_set_tx_key(iwm, iwm->default_key);
 660}
 661
 662static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 663                                   u16 reason_code)
 664{
 665        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 666
 667        IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
 668
 669        if (iwm->umac_profile_active)
 670                iwm_invalidate_mlme_profile(iwm);
 671
 672        return 0;
 673}
 674
 675static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
 676                                    enum nl80211_tx_power_setting type, int mbm)
 677{
 678        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 679        int ret;
 680
 681        switch (type) {
 682        case NL80211_TX_POWER_AUTOMATIC:
 683                return 0;
 684        case NL80211_TX_POWER_FIXED:
 685                if (mbm < 0 || (mbm % 100))
 686                        return -EOPNOTSUPP;
 687
 688                if (!test_bit(IWM_STATUS_READY, &iwm->status))
 689                        return 0;
 690
 691                ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
 692                                              CFG_TX_PWR_LIMIT_USR,
 693                                              MBM_TO_DBM(mbm) * 2);
 694                if (ret < 0)
 695                        return ret;
 696
 697                return iwm_tx_power_trigger(iwm);
 698        default:
 699                IWM_ERR(iwm, "Unsupported power type: %d\n", type);
 700                return -EOPNOTSUPP;
 701        }
 702
 703        return 0;
 704}
 705
 706static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
 707{
 708        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 709
 710        *dbm = iwm->txpower >> 1;
 711
 712        return 0;
 713}
 714
 715static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 716                                       struct net_device *dev,
 717                                       bool enabled, int timeout)
 718{
 719        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 720        u32 power_index;
 721
 722        if (enabled)
 723                power_index = IWM_POWER_INDEX_DEFAULT;
 724        else
 725                power_index = IWM_POWER_INDEX_MIN;
 726
 727        if (power_index == iwm->conf.power_index)
 728                return 0;
 729
 730        iwm->conf.power_index = power_index;
 731
 732        return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
 733                                       CFG_POWER_INDEX, iwm->conf.power_index);
 734}
 735
 736static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
 737                                  struct net_device *netdev,
 738                                  struct cfg80211_pmksa *pmksa)
 739{
 740        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 741
 742        return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
 743}
 744
 745static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
 746                                  struct net_device *netdev,
 747                                  struct cfg80211_pmksa *pmksa)
 748{
 749        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 750
 751        return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
 752}
 753
 754static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
 755                                    struct net_device *netdev)
 756{
 757        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 758        struct cfg80211_pmksa pmksa;
 759
 760        memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
 761
 762        return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
 763}
 764
 765
 766static struct cfg80211_ops iwm_cfg80211_ops = {
 767        .change_virtual_intf = iwm_cfg80211_change_iface,
 768        .add_key = iwm_cfg80211_add_key,
 769        .get_key = iwm_cfg80211_get_key,
 770        .del_key = iwm_cfg80211_del_key,
 771        .set_default_key = iwm_cfg80211_set_default_key,
 772        .get_station = iwm_cfg80211_get_station,
 773        .scan = iwm_cfg80211_scan,
 774        .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
 775        .connect = iwm_cfg80211_connect,
 776        .disconnect = iwm_cfg80211_disconnect,
 777        .join_ibss = iwm_cfg80211_join_ibss,
 778        .leave_ibss = iwm_cfg80211_leave_ibss,
 779        .set_tx_power = iwm_cfg80211_set_txpower,
 780        .get_tx_power = iwm_cfg80211_get_txpower,
 781        .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
 782        .set_pmksa = iwm_cfg80211_set_pmksa,
 783        .del_pmksa = iwm_cfg80211_del_pmksa,
 784        .flush_pmksa = iwm_cfg80211_flush_pmksa,
 785};
 786
 787static const u32 cipher_suites[] = {
 788        WLAN_CIPHER_SUITE_WEP40,
 789        WLAN_CIPHER_SUITE_WEP104,
 790        WLAN_CIPHER_SUITE_TKIP,
 791        WLAN_CIPHER_SUITE_CCMP,
 792};
 793
 794struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
 795{
 796        int ret = 0;
 797        struct wireless_dev *wdev;
 798
 799        /*
 800         * We're trying to have the following memory
 801         * layout:
 802         *
 803         * +-------------------------+
 804         * | struct wiphy            |
 805         * +-------------------------+
 806         * | struct iwm_priv         |
 807         * +-------------------------+
 808         * | bus private data        |
 809         * | (e.g. iwm_priv_sdio)    |
 810         * +-------------------------+
 811         *
 812         */
 813
 814        wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
 815        if (!wdev) {
 816                dev_err(dev, "Couldn't allocate wireless device\n");
 817                return ERR_PTR(-ENOMEM);
 818        }
 819
 820        wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
 821                                sizeof(struct iwm_priv) + sizeof_bus);
 822        if (!wdev->wiphy) {
 823                dev_err(dev, "Couldn't allocate wiphy device\n");
 824                ret = -ENOMEM;
 825                goto out_err_new;
 826        }
 827
 828        set_wiphy_dev(wdev->wiphy, dev);
 829        wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
 830        wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
 831        wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 832                                       BIT(NL80211_IFTYPE_ADHOC);
 833        wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
 834        wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
 835        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 836
 837        wdev->wiphy->cipher_suites = cipher_suites;
 838        wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 839
 840        ret = wiphy_register(wdev->wiphy);
 841        if (ret < 0) {
 842                dev_err(dev, "Couldn't register wiphy device\n");
 843                goto out_err_register;
 844        }
 845
 846        return wdev;
 847
 848 out_err_register:
 849        wiphy_free(wdev->wiphy);
 850
 851 out_err_new:
 852        kfree(wdev);
 853
 854        return ERR_PTR(ret);
 855}
 856
 857void iwm_wdev_free(struct iwm_priv *iwm)
 858{
 859        struct wireless_dev *wdev = iwm_to_wdev(iwm);
 860
 861        if (!wdev)
 862                return;
 863
 864        wiphy_unregister(wdev->wiphy);
 865        wiphy_free(wdev->wiphy);
 866        kfree(wdev);
 867}
 868