iwmc3200wifi: remove key caches in driver
[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         if (!wpa_version) {
488                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
489                 return 0;
490         }
491
492         if (wpa_version & NL80211_WPA_VERSION_2)
493                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
494
495         if (wpa_version & NL80211_WPA_VERSION_1)
496                 iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
497
498         return 0;
499 }
500
501 static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
502 {
503         u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
504                 &iwm->umac_profile->sec.mcast_cipher;
505
506         if (!cipher) {
507                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
508                 return 0;
509         }
510
511         switch (cipher) {
512         case IW_AUTH_CIPHER_NONE:
513                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
514                 break;
515         case WLAN_CIPHER_SUITE_WEP40:
516                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
517                 break;
518         case WLAN_CIPHER_SUITE_WEP104:
519                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
520                 break;
521         case WLAN_CIPHER_SUITE_TKIP:
522                 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
523                 break;
524         case WLAN_CIPHER_SUITE_CCMP:
525                 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
526                 break;
527         default:
528                 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
529                 return -ENOTSUPP;
530         }
531
532         return 0;
533 }
534
535 static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
536 {
537         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
538
539         IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
540
541         if (key_mgt == WLAN_AKM_SUITE_8021X)
542                 *auth_type = UMAC_AUTH_TYPE_8021X;
543         else if (key_mgt == WLAN_AKM_SUITE_PSK) {
544                 if (iwm->umac_profile->sec.flags &
545                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
546                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
547                 else
548                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
549         } else {
550                 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
551                 return -EINVAL;
552         }
553
554         return 0;
555 }
556
557
558 static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
559                                  struct cfg80211_connect_params *sme)
560 {
561         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
562         struct ieee80211_channel *chan = sme->channel;
563         int ret;
564
565         if (!test_bit(IWM_STATUS_READY, &iwm->status))
566                 return -EIO;
567
568         if (!sme->ssid)
569                 return -EINVAL;
570
571         if (chan)
572                 iwm->channel =
573                         ieee80211_frequency_to_channel(chan->center_freq);
574
575         iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
576         memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
577
578         if (sme->bssid) {
579                 IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
580                 memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
581                 iwm->umac_profile->bss_num = 1;
582         } else {
583                 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
584                 iwm->umac_profile->bss_num = 0;
585         }
586
587         ret = iwm_set_auth_type(iwm, sme->auth_type);
588         if (ret < 0)
589                 return ret;
590
591         ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
592         if (ret < 0)
593                 return ret;
594
595         if (sme->crypto.n_ciphers_pairwise) {
596                 ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
597                                      true);
598                 if (ret < 0)
599                         return ret;
600         }
601
602         ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
603         if (ret < 0)
604                 return ret;
605
606         if (sme->crypto.n_akm_suites) {
607                 ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
608                 if (ret < 0)
609                         return ret;
610         }
611
612         return iwm_send_mlme_profile(iwm);
613 }
614
615 static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
616                                    u16 reason_code)
617 {
618         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
619
620         IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
621
622         if (iwm->umac_profile_active)
623                 return iwm_invalidate_mlme_profile(iwm);
624
625         return 0;
626 }
627
628 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
629                                     enum tx_power_setting type, int dbm)
630 {
631         switch (type) {
632         case TX_POWER_AUTOMATIC:
633                 return 0;
634         default:
635                 return -EOPNOTSUPP;
636         }
637
638         return 0;
639 }
640
641 static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
642 {
643         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
644
645         *dbm = iwm->txpower;
646
647         return 0;
648 }
649
650 static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
651                                        struct net_device *dev,
652                                        bool enabled, int timeout)
653 {
654         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
655         u32 power_index;
656
657         if (enabled)
658                 power_index = IWM_POWER_INDEX_DEFAULT;
659         else
660                 power_index = IWM_POWER_INDEX_MIN;
661
662         if (power_index == iwm->conf.power_index)
663                 return 0;
664
665         iwm->conf.power_index = power_index;
666
667         return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
668                                        CFG_POWER_INDEX, iwm->conf.power_index);
669 }
670
671 static struct cfg80211_ops iwm_cfg80211_ops = {
672         .change_virtual_intf = iwm_cfg80211_change_iface,
673         .add_key = iwm_cfg80211_add_key,
674         .get_key = iwm_cfg80211_get_key,
675         .del_key = iwm_cfg80211_del_key,
676         .set_default_key = iwm_cfg80211_set_default_key,
677         .get_station = iwm_cfg80211_get_station,
678         .scan = iwm_cfg80211_scan,
679         .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
680         .connect = iwm_cfg80211_connect,
681         .disconnect = iwm_cfg80211_disconnect,
682         .join_ibss = iwm_cfg80211_join_ibss,
683         .leave_ibss = iwm_cfg80211_leave_ibss,
684         .set_tx_power = iwm_cfg80211_set_txpower,
685         .get_tx_power = iwm_cfg80211_get_txpower,
686         .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
687 };
688
689 static const u32 cipher_suites[] = {
690         WLAN_CIPHER_SUITE_WEP40,
691         WLAN_CIPHER_SUITE_WEP104,
692         WLAN_CIPHER_SUITE_TKIP,
693         WLAN_CIPHER_SUITE_CCMP,
694 };
695
696 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
697 {
698         int ret = 0;
699         struct wireless_dev *wdev;
700
701         /*
702          * We're trying to have the following memory
703          * layout:
704          *
705          * +-------------------------+
706          * | struct wiphy            |
707          * +-------------------------+
708          * | struct iwm_priv         |
709          * +-------------------------+
710          * | bus private data        |
711          * | (e.g. iwm_priv_sdio)    |
712          * +-------------------------+
713          *
714          */
715
716         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
717         if (!wdev) {
718                 dev_err(dev, "Couldn't allocate wireless device\n");
719                 return ERR_PTR(-ENOMEM);
720         }
721
722         wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
723                                 sizeof(struct iwm_priv) + sizeof_bus);
724         if (!wdev->wiphy) {
725                 dev_err(dev, "Couldn't allocate wiphy device\n");
726                 ret = -ENOMEM;
727                 goto out_err_new;
728         }
729
730         set_wiphy_dev(wdev->wiphy, dev);
731         wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
732         wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
733                                        BIT(NL80211_IFTYPE_ADHOC);
734         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
735         wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
736         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
737
738         wdev->wiphy->cipher_suites = cipher_suites;
739         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
740
741         ret = wiphy_register(wdev->wiphy);
742         if (ret < 0) {
743                 dev_err(dev, "Couldn't register wiphy device\n");
744                 goto out_err_register;
745         }
746
747         return wdev;
748
749  out_err_register:
750         wiphy_free(wdev->wiphy);
751
752  out_err_new:
753         kfree(wdev);
754
755         return ERR_PTR(ret);
756 }
757
758 void iwm_wdev_free(struct iwm_priv *iwm)
759 {
760         struct wireless_dev *wdev = iwm_to_wdev(iwm);
761
762         if (!wdev)
763                 return;
764
765         wiphy_unregister(wdev->wiphy);
766         wiphy_free(wdev->wiphy);
767         kfree(wdev);
768 }