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