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