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