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