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;
 191        struct key_params params;
 192
 193        IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
 194
 195        if (key_index >= IWM_NUM_KEYS)
 196                return -ENOENT;
 197
 198        memset(&params, 0, sizeof(params));
 199
 200        key = &iwm->keys[key_index];
 201        params.cipher = key->cipher;
 202        params.key_len = key->key_len;
 203        params.seq_len = key->seq_len;
 204        params.seq = key->seq;
 205        params.key = key->key;
 206
 207        callback(cookie, &params);
 208
 209        return key->key_len ? 0 : -ENOENT;
 210}
 211
 212
 213static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 214                                u8 key_index, bool pairwise, const u8 *mac_addr)
 215{
 216        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 217        struct iwm_key *key = &iwm->keys[key_index];
 218
 219        if (!iwm->keys[key_index].key_len) {
 220                IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
 221                return 0;
 222        }
 223
 224        if (key_index == iwm->default_key)
 225                iwm->default_key = -1;
 226
 227        return iwm_set_key(iwm, 1, key);
 228}
 229
 230static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
 231                                        struct net_device *ndev,
 232                                        u8 key_index, bool unicast,
 233                                        bool multicast)
 234{
 235        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 236
 237        IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
 238
 239        if (!iwm->keys[key_index].key_len) {
 240                IWM_ERR(iwm, "Key %d not used\n", key_index);
 241                return -EINVAL;
 242        }
 243
 244        iwm->default_key = key_index;
 245
 246        return iwm_set_tx_key(iwm, key_index);
 247}
 248
 249static int iwm_cfg80211_get_station(struct wiphy *wiphy,
 250                                    struct net_device *ndev,
 251                                    u8 *mac, struct station_info *sinfo)
 252{
 253        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 254
 255        if (memcmp(mac, iwm->bssid, ETH_ALEN))
 256                return -ENOENT;
 257
 258        sinfo->filled |= STATION_INFO_TX_BITRATE;
 259        sinfo->txrate.legacy = iwm->rate * 10;
 260
 261        if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
 262                sinfo->filled |= STATION_INFO_SIGNAL;
 263                sinfo->signal = iwm->wstats.qual.level;
 264        }
 265
 266        return 0;
 267}
 268
 269
 270int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
 271{
 272        struct wiphy *wiphy = iwm_to_wiphy(iwm);
 273        struct iwm_bss_info *bss;
 274        struct iwm_umac_notif_bss_info *umac_bss;
 275        struct ieee80211_mgmt *mgmt;
 276        struct ieee80211_channel *channel;
 277        struct ieee80211_supported_band *band;
 278        s32 signal;
 279        int freq;
 280
 281        list_for_each_entry(bss, &iwm->bss_list, node) {
 282                umac_bss = bss->bss;
 283                mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
 284
 285                if (umac_bss->band == UMAC_BAND_2GHZ)
 286                        band = wiphy->bands[IEEE80211_BAND_2GHZ];
 287                else if (umac_bss->band == UMAC_BAND_5GHZ)
 288                        band = wiphy->bands[IEEE80211_BAND_5GHZ];
 289                else {
 290                        IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
 291                        return -EINVAL;
 292                }
 293
 294                freq = ieee80211_channel_to_frequency(umac_bss->channel,
 295                                                      band->band);
 296                channel = ieee80211_get_channel(wiphy, freq);
 297                signal = umac_bss->rssi * 100;
 298
 299                if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
 300                                               le16_to_cpu(umac_bss->frame_len),
 301                                               signal, GFP_KERNEL))
 302                        return -EINVAL;
 303        }
 304
 305        return 0;
 306}
 307
 308static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
 309                                     struct net_device *ndev,
 310                                     enum nl80211_iftype type, u32 *flags,
 311                                     struct vif_params *params)
 312{
 313        struct wireless_dev *wdev;
 314        struct iwm_priv *iwm;
 315        u32 old_mode;
 316
 317        wdev = ndev->ieee80211_ptr;
 318        iwm = ndev_to_iwm(ndev);
 319        old_mode = iwm->conf.mode;
 320
 321        switch (type) {
 322        case NL80211_IFTYPE_STATION:
 323                iwm->conf.mode = UMAC_MODE_BSS;
 324                break;
 325        case NL80211_IFTYPE_ADHOC:
 326                iwm->conf.mode = UMAC_MODE_IBSS;
 327                break;
 328        default:
 329                return -EOPNOTSUPP;
 330        }
 331
 332        wdev->iftype = type;
 333
 334        if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
 335                return 0;
 336
 337        iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
 338
 339        if (iwm->umac_profile_active)
 340                iwm_invalidate_mlme_profile(iwm);
 341
 342        return 0;
 343}
 344
 345static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 346                             struct cfg80211_scan_request *request)
 347{
 348        struct iwm_priv *iwm = ndev_to_iwm(ndev);
 349        int ret;
 350
 351        if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
 352                IWM_ERR(iwm, "Scan while device is not ready\n");
 353                return -EIO;
 354        }
 355
 356        if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
 357                IWM_ERR(iwm, "Scanning already\n");
 358                return -EAGAIN;
 359        }
 360
 361        if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
 362                IWM_ERR(iwm, "Scanning being aborted\n");
 363                return -EAGAIN;
 364        }
 365
 366        set_bit(IWM_STATUS_SCANNING, &iwm->status);
 367
 368        ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
 369        if (ret) {
 370                clear_bit(IWM_STATUS_SCANNING, &iwm->status);
 371                return ret;
 372        }
 373
 374        iwm->scan_request = request;
 375        return 0;
 376}
 377
 378static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 379{
 380        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 381
 382        if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
 383            (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
 384                int ret;
 385
 386                iwm->conf.rts_threshold = wiphy->rts_threshold;
 387
 388                ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
 389                                             CFG_RTS_THRESHOLD,
 390                                             iwm->conf.rts_threshold);
 391                if (ret < 0)
 392                        return ret;
 393        }
 394
 395        if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
 396            (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
 397                int ret;
 398
 399                iwm->conf.frag_threshold = wiphy->frag_threshold;
 400
 401                ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
 402                                             CFG_FRAG_THRESHOLD,
 403                                             iwm->conf.frag_threshold);
 404                if (ret < 0)
 405                        return ret;
 406        }
 407
 408        return 0;
 409}
 410
 411static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 412                                  struct cfg80211_ibss_params *params)
 413{
 414        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 415        struct ieee80211_channel *chan = params->channel;
 416
 417        if (!test_bit(IWM_STATUS_READY, &iwm->status))
 418                return -EIO;
 419
 420        /* UMAC doesn't support creating or joining an IBSS network
 421         * with specified bssid. */
 422        if (params->bssid)
 423                return -EOPNOTSUPP;
 424
 425        iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
 426        iwm->umac_profile->ibss.band = chan->band;
 427        iwm->umac_profile->ibss.channel = iwm->channel;
 428        iwm->umac_profile->ssid.ssid_len = params->ssid_len;
 429        memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
 430
 431        return iwm_send_mlme_profile(iwm);
 432}
 433
 434static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 435{
 436        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 437
 438        if (iwm->umac_profile_active)
 439                return iwm_invalidate_mlme_profile(iwm);
 440
 441        return 0;
 442}
 443
 444static int iwm_set_auth_type(struct iwm_priv *iwm,
 445                             enum nl80211_auth_type sme_auth_type)
 446{
 447        u8 *auth_type = &iwm->umac_profile->sec.auth_type;
 448
 449        switch (sme_auth_type) {
 450        case NL80211_AUTHTYPE_AUTOMATIC:
 451        case NL80211_AUTHTYPE_OPEN_SYSTEM:
 452                IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
 453                *auth_type = UMAC_AUTH_TYPE_OPEN;
 454                break;
 455        case NL80211_AUTHTYPE_SHARED_KEY:
 456                if (iwm->umac_profile->sec.flags &
 457                    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
 458                        IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
 459                        *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
 460                } else {
 461                        IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
 462                        *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
 463                }
 464
 465                break;
 466        default:
 467                IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
 468                return -ENOTSUPP;
 469        }
 470
 471        return 0;
 472}
 473
 474static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
 475{
 476        IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
 477
 478        if (!wpa_version) {
 479                iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
 480                return 0;
 481        }
 482
 483        if (wpa_version & NL80211_WPA_VERSION_1)
 484                iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
 485
 486        if (wpa_version & NL80211_WPA_VERSION_2)
 487                iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
 488
 489        return 0;
 490}
 491
 492static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
 493{
 494        u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
 495                &iwm->umac_profile->sec.mcast_cipher;
 496
 497        if (!cipher) {
 498                *profile_cipher = UMAC_CIPHER_TYPE_NONE;
 499                return 0;
 500        }
 501
 502        IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
 503                     cipher);
 504
 505        switch (cipher) {
 506        case IW_AUTH_CIPHER_NONE:
 507                *profile_cipher = UMAC_CIPHER_TYPE_NONE;
 508                break;
 509        case WLAN_CIPHER_SUITE_WEP40:
 510                *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
 511                break;
 512        case WLAN_CIPHER_SUITE_WEP104:
 513                *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
 514                break;
 515        case WLAN_CIPHER_SUITE_TKIP:
 516                *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
 517                break;
 518        case WLAN_CIPHER_SUITE_CCMP:
 519                *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
 520                break;
 521        default:
 522                IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
 523                return -ENOTSUPP;
 524        }
 525
 526        return 0;
 527}
 528
 529static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
 530{
 531        u8 *auth_type = &iwm->umac_profile->sec.auth_type;
 532
 533        IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
 534
 535        if (key_mgt == WLAN_AKM_SUITE_8021X)
 536                *auth_type = UMAC_AUTH_TYPE_8021X;
 537        else if (key_mgt == WLAN_AKM_SUITE_PSK) {
 538                if (iwm->umac_profile->sec.flags &
 539                    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
 540                        *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
 541                else
 542                        *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
 543        } else {
 544                IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
 545                return -EINVAL;
 546        }
 547
 548        return 0;
 549}
 550
 551
 552static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 553                                 struct cfg80211_connect_params *sme)
 554{
 555        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 556        struct ieee80211_channel *chan = sme->channel;
 557        struct key_params key_param;
 558        int ret;
 559
 560        if (!test_bit(IWM_STATUS_READY, &iwm->status))
 561                return -EIO;
 562
 563        if (!sme->ssid)
 564                return -EINVAL;
 565
 566        if (iwm->umac_profile_active) {
 567                ret = iwm_invalidate_mlme_profile(iwm);
 568                if (ret) {
 569                        IWM_ERR(iwm, "Couldn't invalidate profile\n");
 570                        return ret;
 571                }
 572        }
 573
 574        if (chan)
 575                iwm->channel =
 576                        ieee80211_frequency_to_channel(chan->center_freq);
 577
 578        iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
 579        memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
 580
 581        if (sme->bssid) {
 582                IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
 583                memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
 584                iwm->umac_profile->bss_num = 1;
 585        } else {
 586                memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
 587                iwm->umac_profile->bss_num = 0;
 588        }
 589
 590        ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
 591        if (ret < 0)
 592                return ret;
 593
 594        ret = iwm_set_auth_type(iwm, sme->auth_type);
 595        if (ret < 0)
 596                return ret;
 597
 598        if (sme->crypto.n_ciphers_pairwise) {
 599                ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
 600                                     true);
 601                if (ret < 0)
 602                        return ret;
 603        }
 604
 605        ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
 606        if (ret < 0)
 607                return ret;
 608
 609        if (sme->crypto.n_akm_suites) {
 610                ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
 611                if (ret < 0)
 612                        return ret;
 613        }
 614
 615        /*
 616         * We save the WEP key in case we want to do shared authentication.
 617         * We have to do it so because UMAC will assert whenever it gets a
 618         * key before a profile.
 619         */
 620        if (sme->key) {
 621                key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
 622                if (key_param.key == NULL)
 623                        return -ENOMEM;
 624                key_param.key_len = sme->key_len;
 625                key_param.seq_len = 0;
 626                key_param.cipher = sme->crypto.ciphers_pairwise[0];
 627
 628                ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
 629                                   NULL, &key_param);
 630                kfree(key_param.key);
 631                if (ret < 0) {
 632                        IWM_ERR(iwm, "Invalid key_params\n");
 633                        return ret;
 634                }
 635
 636                iwm->default_key = sme->key_idx;
 637        }
 638
 639        /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
 640        if ((iwm->umac_profile->sec.flags &
 641             (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
 642            iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
 643                        iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
 644        }
 645
 646        ret = iwm_send_mlme_profile(iwm);
 647
 648        if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
 649            sme->key == NULL)
 650                return ret;
 651
 652        /*
 653         * We want to do shared auth.
 654         * We need to actually set the key we previously cached,
 655         * and then tell the UMAC it's the default one.
 656         * That will trigger the auth+assoc UMAC machinery, and again,
 657         * this must be done after setting the profile.
 658         */
 659        ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
 660        if (ret < 0)
 661                return ret;
 662
 663        return iwm_set_tx_key(iwm, iwm->default_key);
 664}
 665
 666static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 667                                   u16 reason_code)
 668{
 669        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 670
 671        IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
 672
 673        if (iwm->umac_profile_active)
 674                iwm_invalidate_mlme_profile(iwm);
 675
 676        return 0;
 677}
 678
 679static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
 680                                    enum nl80211_tx_power_setting type, int mbm)
 681{
 682        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 683        int ret;
 684
 685        switch (type) {
 686        case NL80211_TX_POWER_AUTOMATIC:
 687                return 0;
 688        case NL80211_TX_POWER_FIXED:
 689                if (mbm < 0 || (mbm % 100))
 690                        return -EOPNOTSUPP;
 691
 692                if (!test_bit(IWM_STATUS_READY, &iwm->status))
 693                        return 0;
 694
 695                ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
 696                                              CFG_TX_PWR_LIMIT_USR,
 697                                              MBM_TO_DBM(mbm) * 2);
 698                if (ret < 0)
 699                        return ret;
 700
 701                return iwm_tx_power_trigger(iwm);
 702        default:
 703                IWM_ERR(iwm, "Unsupported power type: %d\n", type);
 704                return -EOPNOTSUPP;
 705        }
 706
 707        return 0;
 708}
 709
 710static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
 711{
 712        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 713
 714        *dbm = iwm->txpower >> 1;
 715
 716        return 0;
 717}
 718
 719static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 720                                       struct net_device *dev,
 721                                       bool enabled, int timeout)
 722{
 723        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 724        u32 power_index;
 725
 726        if (enabled)
 727                power_index = IWM_POWER_INDEX_DEFAULT;
 728        else
 729                power_index = IWM_POWER_INDEX_MIN;
 730
 731        if (power_index == iwm->conf.power_index)
 732                return 0;
 733
 734        iwm->conf.power_index = power_index;
 735
 736        return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
 737                                       CFG_POWER_INDEX, iwm->conf.power_index);
 738}
 739
 740static int iwm_cfg80211_set_pmksa(struct wiphy *wiphy,
 741                                  struct net_device *netdev,
 742                                  struct cfg80211_pmksa *pmksa)
 743{
 744        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 745
 746        return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
 747}
 748
 749static int iwm_cfg80211_del_pmksa(struct wiphy *wiphy,
 750                                  struct net_device *netdev,
 751                                  struct cfg80211_pmksa *pmksa)
 752{
 753        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 754
 755        return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
 756}
 757
 758static int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy,
 759                                    struct net_device *netdev)
 760{
 761        struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 762        struct cfg80211_pmksa pmksa;
 763
 764        memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
 765
 766        return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
 767}
 768
 769
 770static struct cfg80211_ops iwm_cfg80211_ops = {
 771        .change_virtual_intf = iwm_cfg80211_change_iface,
 772        .add_key = iwm_cfg80211_add_key,
 773        .get_key = iwm_cfg80211_get_key,
 774        .del_key = iwm_cfg80211_del_key,
 775        .set_default_key = iwm_cfg80211_set_default_key,
 776        .get_station = iwm_cfg80211_get_station,
 777        .scan = iwm_cfg80211_scan,
 778        .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
 779        .connect = iwm_cfg80211_connect,
 780        .disconnect = iwm_cfg80211_disconnect,
 781        .join_ibss = iwm_cfg80211_join_ibss,
 782        .leave_ibss = iwm_cfg80211_leave_ibss,
 783        .set_tx_power = iwm_cfg80211_set_txpower,
 784        .get_tx_power = iwm_cfg80211_get_txpower,
 785        .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
 786        .set_pmksa = iwm_cfg80211_set_pmksa,
 787        .del_pmksa = iwm_cfg80211_del_pmksa,
 788        .flush_pmksa = iwm_cfg80211_flush_pmksa,
 789};
 790
 791static const u32 cipher_suites[] = {
 792        WLAN_CIPHER_SUITE_WEP40,
 793        WLAN_CIPHER_SUITE_WEP104,
 794        WLAN_CIPHER_SUITE_TKIP,
 795        WLAN_CIPHER_SUITE_CCMP,
 796};
 797
 798struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
 799{
 800        int ret = 0;
 801        struct wireless_dev *wdev;
 802
 803        /*
 804         * We're trying to have the following memory
 805         * layout:
 806         *
 807         * +-------------------------+
 808         * | struct wiphy            |
 809         * +-------------------------+
 810         * | struct iwm_priv         |
 811         * +-------------------------+
 812         * | bus private data        |
 813         * | (e.g. iwm_priv_sdio)    |
 814         * +-------------------------+
 815         *
 816         */
 817
 818        wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
 819        if (!wdev) {
 820                dev_err(dev, "Couldn't allocate wireless device\n");
 821                return ERR_PTR(-ENOMEM);
 822        }
 823
 824        wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
 825                                sizeof(struct iwm_priv) + sizeof_bus);
 826        if (!wdev->wiphy) {
 827                dev_err(dev, "Couldn't allocate wiphy device\n");
 828                ret = -ENOMEM;
 829                goto out_err_new;
 830        }
 831
 832        set_wiphy_dev(wdev->wiphy, dev);
 833        wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
 834        wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
 835        wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 836                                       BIT(NL80211_IFTYPE_ADHOC);
 837        wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
 838        wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
 839        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 840
 841        wdev->wiphy->cipher_suites = cipher_suites;
 842        wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 843
 844        ret = wiphy_register(wdev->wiphy);
 845        if (ret < 0) {
 846                dev_err(dev, "Couldn't register wiphy device\n");
 847                goto out_err_register;
 848        }
 849
 850        return wdev;
 851
 852 out_err_register:
 853        wiphy_free(wdev->wiphy);
 854
 855 out_err_new:
 856        kfree(wdev);
 857
 858        return ERR_PTR(ret);
 859}
 860
 861void iwm_wdev_free(struct iwm_priv *iwm)
 862{
 863        struct wireless_dev *wdev = iwm_to_wdev(iwm);
 864
 865        if (!wdev)
 866                return;
 867
 868        wiphy_unregister(wdev->wiphy);
 869        wiphy_free(wdev->wiphy);
 870        kfree(wdev);
 871}
 872