iwmc3200wifi: fix set_wpa_version and set_auth_type order
[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_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
178         return iwm_set_key(iwm, 0, key);
179 }
180
181 static 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
206 static 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
223 static 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);
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
236         iwm->default_key = key_index;
237
238         return iwm_set_tx_key(iwm, key_index);
239 }
240
241 int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
242                              u8 *mac, struct station_info *sinfo)
243 {
244         struct iwm_priv *iwm = ndev_to_iwm(ndev);
245
246         if (memcmp(mac, iwm->bssid, ETH_ALEN))
247                 return -ENOENT;
248
249         sinfo->filled |= STATION_INFO_TX_BITRATE;
250         sinfo->txrate.legacy = iwm->rate * 10;
251
252         if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
253                 sinfo->filled |= STATION_INFO_SIGNAL;
254                 sinfo->signal = iwm->wstats.qual.level;
255         }
256
257         return 0;
258 }
259
260
261 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
262 {
263         struct wiphy *wiphy = iwm_to_wiphy(iwm);
264         struct iwm_bss_info *bss, *next;
265         struct iwm_umac_notif_bss_info *umac_bss;
266         struct ieee80211_mgmt *mgmt;
267         struct ieee80211_channel *channel;
268         struct ieee80211_supported_band *band;
269         s32 signal;
270         int freq;
271
272         list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
273                 umac_bss = bss->bss;
274                 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
275
276                 if (umac_bss->band == UMAC_BAND_2GHZ)
277                         band = wiphy->bands[IEEE80211_BAND_2GHZ];
278                 else if (umac_bss->band == UMAC_BAND_5GHZ)
279                         band = wiphy->bands[IEEE80211_BAND_5GHZ];
280                 else {
281                         IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
282                         return -EINVAL;
283                 }
284
285                 freq = ieee80211_channel_to_frequency(umac_bss->channel);
286                 channel = ieee80211_get_channel(wiphy, freq);
287                 signal = umac_bss->rssi * 100;
288
289                 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
290                                                le16_to_cpu(umac_bss->frame_len),
291                                                signal, GFP_KERNEL))
292                         return -EINVAL;
293         }
294
295         return 0;
296 }
297
298 static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
299                                      struct net_device *ndev,
300                                      enum nl80211_iftype type, u32 *flags,
301                                      struct vif_params *params)
302 {
303         struct wireless_dev *wdev;
304         struct iwm_priv *iwm;
305         u32 old_mode;
306
307         wdev = ndev->ieee80211_ptr;
308         iwm = ndev_to_iwm(ndev);
309         old_mode = iwm->conf.mode;
310
311         switch (type) {
312         case NL80211_IFTYPE_STATION:
313                 iwm->conf.mode = UMAC_MODE_BSS;
314                 break;
315         case NL80211_IFTYPE_ADHOC:
316                 iwm->conf.mode = UMAC_MODE_IBSS;
317                 break;
318         default:
319                 return -EOPNOTSUPP;
320         }
321
322         wdev->iftype = type;
323
324         if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
325                 return 0;
326
327         iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
328
329         if (iwm->umac_profile_active) {
330                 int ret = iwm_invalidate_mlme_profile(iwm);
331                 if (ret < 0)
332                         IWM_ERR(iwm, "Couldn't invalidate profile\n");
333         }
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         struct cfg80211_bss *bss;
410
411         if (!test_bit(IWM_STATUS_READY, &iwm->status))
412                 return -EIO;
413
414         /* UMAC doesn't support creating IBSS network with specified bssid.
415          * This should be removed after we have join only mode supported. */
416         if (params->bssid)
417                 return -EOPNOTSUPP;
418
419         bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
420                                 params->ssid, params->ssid_len);
421         if (!bss) {
422                 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
423                 schedule_timeout_interruptible(2 * HZ);
424                 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
425                                         params->ssid, params->ssid_len);
426         }
427         /* IBSS join only mode is not supported by UMAC ATM */
428         if (bss) {
429                 cfg80211_put_bss(bss);
430                 return -EOPNOTSUPP;
431         }
432
433         iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
434         iwm->umac_profile->ibss.band = chan->band;
435         iwm->umac_profile->ibss.channel = iwm->channel;
436         iwm->umac_profile->ssid.ssid_len = params->ssid_len;
437         memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
438
439         if (params->bssid)
440                 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
441
442         return iwm_send_mlme_profile(iwm);
443 }
444
445 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
446 {
447         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
448
449         if (iwm->umac_profile_active)
450                 return iwm_invalidate_mlme_profile(iwm);
451
452         return 0;
453 }
454
455 static int iwm_set_auth_type(struct iwm_priv *iwm,
456                              enum nl80211_auth_type sme_auth_type)
457 {
458         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
459
460         switch (sme_auth_type) {
461         case NL80211_AUTHTYPE_AUTOMATIC:
462         case NL80211_AUTHTYPE_OPEN_SYSTEM:
463                 IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
464                 *auth_type = UMAC_AUTH_TYPE_OPEN;
465                 break;
466         case NL80211_AUTHTYPE_SHARED_KEY:
467                 if (iwm->umac_profile->sec.flags &
468                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
469                         IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
470                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
471                 } else {
472                         IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
473                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
474                 }
475
476                 break;
477         default:
478                 IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
479                 return -ENOTSUPP;
480         }
481
482         return 0;
483 }
484
485 static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
486 {
487         IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
488
489         if (!wpa_version) {
490                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
491                 return 0;
492         }
493
494         if (wpa_version & NL80211_WPA_VERSION_2)
495                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
496
497         if (wpa_version & NL80211_WPA_VERSION_1)
498                 iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
499
500         return 0;
501 }
502
503 static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
504 {
505         u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
506                 &iwm->umac_profile->sec.mcast_cipher;
507
508         if (!cipher) {
509                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
510                 return 0;
511         }
512
513         IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
514                      cipher);
515
516         switch (cipher) {
517         case IW_AUTH_CIPHER_NONE:
518                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
519                 break;
520         case WLAN_CIPHER_SUITE_WEP40:
521                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
522                 break;
523         case WLAN_CIPHER_SUITE_WEP104:
524                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
525                 break;
526         case WLAN_CIPHER_SUITE_TKIP:
527                 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
528                 break;
529         case WLAN_CIPHER_SUITE_CCMP:
530                 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
531                 break;
532         default:
533                 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
534                 return -ENOTSUPP;
535         }
536
537         return 0;
538 }
539
540 static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
541 {
542         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
543
544         IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
545
546         if (key_mgt == WLAN_AKM_SUITE_8021X)
547                 *auth_type = UMAC_AUTH_TYPE_8021X;
548         else if (key_mgt == WLAN_AKM_SUITE_PSK) {
549                 if (iwm->umac_profile->sec.flags &
550                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
551                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
552                 else
553                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
554         } else {
555                 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
556                 return -EINVAL;
557         }
558
559         return 0;
560 }
561
562
563 static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
564                                  struct cfg80211_connect_params *sme)
565 {
566         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
567         struct ieee80211_channel *chan = sme->channel;
568         int ret;
569
570         if (!test_bit(IWM_STATUS_READY, &iwm->status))
571                 return -EIO;
572
573         if (!sme->ssid)
574                 return -EINVAL;
575
576         if (chan)
577                 iwm->channel =
578                         ieee80211_frequency_to_channel(chan->center_freq);
579
580         iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
581         memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
582
583         if (sme->bssid) {
584                 IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
585                 memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
586                 iwm->umac_profile->bss_num = 1;
587         } else {
588                 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
589                 iwm->umac_profile->bss_num = 0;
590         }
591
592         ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
593         if (ret < 0)
594                 return ret;
595
596         ret = iwm_set_auth_type(iwm, sme->auth_type);
597         if (ret < 0)
598                 return ret;
599
600         if (sme->crypto.n_ciphers_pairwise) {
601                 ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
602                                      true);
603                 if (ret < 0)
604                         return ret;
605         }
606
607         ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
608         if (ret < 0)
609                 return ret;
610
611         if (sme->crypto.n_akm_suites) {
612                 ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
613                 if (ret < 0)
614                         return ret;
615         }
616
617         return iwm_send_mlme_profile(iwm);
618 }
619
620 static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
621                                    u16 reason_code)
622 {
623         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
624
625         IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
626
627         if (iwm->umac_profile_active)
628                 return iwm_invalidate_mlme_profile(iwm);
629
630         return 0;
631 }
632
633 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
634                                     enum tx_power_setting type, int dbm)
635 {
636         switch (type) {
637         case TX_POWER_AUTOMATIC:
638                 return 0;
639         default:
640                 return -EOPNOTSUPP;
641         }
642
643         return 0;
644 }
645
646 static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
647 {
648         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
649
650         *dbm = iwm->txpower;
651
652         return 0;
653 }
654
655 static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
656                                        struct net_device *dev,
657                                        bool enabled, int timeout)
658 {
659         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
660         u32 power_index;
661
662         if (enabled)
663                 power_index = IWM_POWER_INDEX_DEFAULT;
664         else
665                 power_index = IWM_POWER_INDEX_MIN;
666
667         if (power_index == iwm->conf.power_index)
668                 return 0;
669
670         iwm->conf.power_index = power_index;
671
672         return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
673                                        CFG_POWER_INDEX, iwm->conf.power_index);
674 }
675
676 static struct cfg80211_ops iwm_cfg80211_ops = {
677         .change_virtual_intf = iwm_cfg80211_change_iface,
678         .add_key = iwm_cfg80211_add_key,
679         .get_key = iwm_cfg80211_get_key,
680         .del_key = iwm_cfg80211_del_key,
681         .set_default_key = iwm_cfg80211_set_default_key,
682         .get_station = iwm_cfg80211_get_station,
683         .scan = iwm_cfg80211_scan,
684         .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
685         .connect = iwm_cfg80211_connect,
686         .disconnect = iwm_cfg80211_disconnect,
687         .join_ibss = iwm_cfg80211_join_ibss,
688         .leave_ibss = iwm_cfg80211_leave_ibss,
689         .set_tx_power = iwm_cfg80211_set_txpower,
690         .get_tx_power = iwm_cfg80211_get_txpower,
691         .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
692 };
693
694 static const u32 cipher_suites[] = {
695         WLAN_CIPHER_SUITE_WEP40,
696         WLAN_CIPHER_SUITE_WEP104,
697         WLAN_CIPHER_SUITE_TKIP,
698         WLAN_CIPHER_SUITE_CCMP,
699 };
700
701 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
702 {
703         int ret = 0;
704         struct wireless_dev *wdev;
705
706         /*
707          * We're trying to have the following memory
708          * layout:
709          *
710          * +-------------------------+
711          * | struct wiphy            |
712          * +-------------------------+
713          * | struct iwm_priv         |
714          * +-------------------------+
715          * | bus private data        |
716          * | (e.g. iwm_priv_sdio)    |
717          * +-------------------------+
718          *
719          */
720
721         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
722         if (!wdev) {
723                 dev_err(dev, "Couldn't allocate wireless device\n");
724                 return ERR_PTR(-ENOMEM);
725         }
726
727         wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
728                                 sizeof(struct iwm_priv) + sizeof_bus);
729         if (!wdev->wiphy) {
730                 dev_err(dev, "Couldn't allocate wiphy device\n");
731                 ret = -ENOMEM;
732                 goto out_err_new;
733         }
734
735         set_wiphy_dev(wdev->wiphy, dev);
736         wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
737         wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
738                                        BIT(NL80211_IFTYPE_ADHOC);
739         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
740         wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
741         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
742
743         wdev->wiphy->cipher_suites = cipher_suites;
744         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
745
746         ret = wiphy_register(wdev->wiphy);
747         if (ret < 0) {
748                 dev_err(dev, "Couldn't register wiphy device\n");
749                 goto out_err_register;
750         }
751
752         return wdev;
753
754  out_err_register:
755         wiphy_free(wdev->wiphy);
756
757  out_err_new:
758         kfree(wdev);
759
760         return ERR_PTR(ret);
761 }
762
763 void iwm_wdev_free(struct iwm_priv *iwm)
764 {
765         struct wireless_dev *wdev = iwm_to_wdev(iwm);
766
767         if (!wdev)
768                 return;
769
770         wiphy_unregister(wdev->wiphy);
771         wiphy_free(wdev->wiphy);
772         kfree(wdev);
773 }