~ubuntu-branches/ubuntu/natty/linux-backports-modules-2.6.38/natty-proposed

« back to all changes in this revision

Viewing changes to updates/compat-wireless-2.6.36/drivers/net/wireless/iwmc3200wifi/cfg80211.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Gardner, Tim Gardner
  • Date: 2011-06-08 10:44:09 UTC
  • Revision ID: james.westby@ubuntu.com-20110608104409-fnl8carkdo15bwsz
Tags: 2.6.38-10.6
[ Tim Gardner ]

Shorten compat-wireless package name to cw to accomodate
CDROM file name length restrictions.

Show diffs side-by-side

added added

removed removed

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