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