iwmc3200wifi: invalidate profile when necessary before connect
[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                 iwm_invalidate_mlme_profile(iwm);
331
332         return 0;
333 }
334
335 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
336                              struct cfg80211_scan_request *request)
337 {
338         struct iwm_priv *iwm = ndev_to_iwm(ndev);
339         int ret;
340
341         if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
342                 IWM_ERR(iwm, "Scan while device is not ready\n");
343                 return -EIO;
344         }
345
346         if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
347                 IWM_ERR(iwm, "Scanning already\n");
348                 return -EAGAIN;
349         }
350
351         if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
352                 IWM_ERR(iwm, "Scanning being aborted\n");
353                 return -EAGAIN;
354         }
355
356         set_bit(IWM_STATUS_SCANNING, &iwm->status);
357
358         ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
359         if (ret) {
360                 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
361                 return ret;
362         }
363
364         iwm->scan_request = request;
365         return 0;
366 }
367
368 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
369 {
370         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
371
372         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
373             (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
374                 int ret;
375
376                 iwm->conf.rts_threshold = wiphy->rts_threshold;
377
378                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
379                                              CFG_RTS_THRESHOLD,
380                                              iwm->conf.rts_threshold);
381                 if (ret < 0)
382                         return ret;
383         }
384
385         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
386             (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
387                 int ret;
388
389                 iwm->conf.frag_threshold = wiphy->frag_threshold;
390
391                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
392                                              CFG_FRAG_THRESHOLD,
393                                              iwm->conf.frag_threshold);
394                 if (ret < 0)
395                         return ret;
396         }
397
398         return 0;
399 }
400
401 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
402                                   struct cfg80211_ibss_params *params)
403 {
404         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
405         struct ieee80211_channel *chan = params->channel;
406         struct cfg80211_bss *bss;
407
408         if (!test_bit(IWM_STATUS_READY, &iwm->status))
409                 return -EIO;
410
411         /* UMAC doesn't support creating IBSS network with specified bssid.
412          * This should be removed after we have join only mode supported. */
413         if (params->bssid)
414                 return -EOPNOTSUPP;
415
416         bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
417                                 params->ssid, params->ssid_len);
418         if (!bss) {
419                 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
420                 schedule_timeout_interruptible(2 * HZ);
421                 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
422                                         params->ssid, params->ssid_len);
423         }
424         /* IBSS join only mode is not supported by UMAC ATM */
425         if (bss) {
426                 cfg80211_put_bss(bss);
427                 return -EOPNOTSUPP;
428         }
429
430         iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
431         iwm->umac_profile->ibss.band = chan->band;
432         iwm->umac_profile->ibss.channel = iwm->channel;
433         iwm->umac_profile->ssid.ssid_len = params->ssid_len;
434         memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
435
436         if (params->bssid)
437                 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
438
439         return iwm_send_mlme_profile(iwm);
440 }
441
442 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
443 {
444         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
445
446         if (iwm->umac_profile_active)
447                 return iwm_invalidate_mlme_profile(iwm);
448
449         return 0;
450 }
451
452 static int iwm_set_auth_type(struct iwm_priv *iwm,
453                              enum nl80211_auth_type sme_auth_type)
454 {
455         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
456
457         switch (sme_auth_type) {
458         case NL80211_AUTHTYPE_AUTOMATIC:
459         case NL80211_AUTHTYPE_OPEN_SYSTEM:
460                 IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
461                 *auth_type = UMAC_AUTH_TYPE_OPEN;
462                 break;
463         case NL80211_AUTHTYPE_SHARED_KEY:
464                 if (iwm->umac_profile->sec.flags &
465                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
466                         IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
467                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
468                 } else {
469                         IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
470                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
471                 }
472
473                 break;
474         default:
475                 IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
476                 return -ENOTSUPP;
477         }
478
479         return 0;
480 }
481
482 static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
483 {
484         IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
485
486         if (!wpa_version) {
487                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
488                 return 0;
489         }
490
491         if (wpa_version & NL80211_WPA_VERSION_2)
492                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
493
494         if (wpa_version & NL80211_WPA_VERSION_1)
495                 iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
496
497         return 0;
498 }
499
500 static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
501 {
502         u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
503                 &iwm->umac_profile->sec.mcast_cipher;
504
505         if (!cipher) {
506                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
507                 return 0;
508         }
509
510         IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
511                      cipher);
512
513         switch (cipher) {
514         case IW_AUTH_CIPHER_NONE:
515                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
516                 break;
517         case WLAN_CIPHER_SUITE_WEP40:
518                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
519                 break;
520         case WLAN_CIPHER_SUITE_WEP104:
521                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
522                 break;
523         case WLAN_CIPHER_SUITE_TKIP:
524                 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
525                 break;
526         case WLAN_CIPHER_SUITE_CCMP:
527                 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
528                 break;
529         default:
530                 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
531                 return -ENOTSUPP;
532         }
533
534         return 0;
535 }
536
537 static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
538 {
539         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
540
541         IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
542
543         if (key_mgt == WLAN_AKM_SUITE_8021X)
544                 *auth_type = UMAC_AUTH_TYPE_8021X;
545         else if (key_mgt == WLAN_AKM_SUITE_PSK) {
546                 if (iwm->umac_profile->sec.flags &
547                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
548                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
549                 else
550                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
551         } else {
552                 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
553                 return -EINVAL;
554         }
555
556         return 0;
557 }
558
559
560 static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
561                                  struct cfg80211_connect_params *sme)
562 {
563         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
564         struct ieee80211_channel *chan = sme->channel;
565         int ret;
566
567         if (!test_bit(IWM_STATUS_READY, &iwm->status))
568                 return -EIO;
569
570         if (!sme->ssid)
571                 return -EINVAL;
572
573         if (iwm->umac_profile_active) {
574                 ret = iwm_invalidate_mlme_profile(iwm);
575                 if (ret) {
576                         IWM_ERR(iwm, "Couldn't invalidate profile\n");
577                         return ret;
578                 }
579         }
580
581         if (chan)
582                 iwm->channel =
583                         ieee80211_frequency_to_channel(chan->center_freq);
584
585         iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
586         memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
587
588         if (sme->bssid) {
589                 IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
590                 memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
591                 iwm->umac_profile->bss_num = 1;
592         } else {
593                 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
594                 iwm->umac_profile->bss_num = 0;
595         }
596
597         ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
598         if (ret < 0)
599                 return ret;
600
601         ret = iwm_set_auth_type(iwm, sme->auth_type);
602         if (ret < 0)
603                 return ret;
604
605         if (sme->crypto.n_ciphers_pairwise) {
606                 ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
607                                      true);
608                 if (ret < 0)
609                         return ret;
610         }
611
612         ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
613         if (ret < 0)
614                 return ret;
615
616         if (sme->crypto.n_akm_suites) {
617                 ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
618                 if (ret < 0)
619                         return ret;
620         }
621
622         return iwm_send_mlme_profile(iwm);
623 }
624
625 static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
626                                    u16 reason_code)
627 {
628         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
629
630         IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
631
632         if (iwm->umac_profile_active)
633                 return iwm_invalidate_mlme_profile(iwm);
634
635         return 0;
636 }
637
638 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
639                                     enum tx_power_setting type, int dbm)
640 {
641         switch (type) {
642         case TX_POWER_AUTOMATIC:
643                 return 0;
644         default:
645                 return -EOPNOTSUPP;
646         }
647
648         return 0;
649 }
650
651 static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
652 {
653         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
654
655         *dbm = iwm->txpower;
656
657         return 0;
658 }
659
660 static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
661                                        struct net_device *dev,
662                                        bool enabled, int timeout)
663 {
664         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
665         u32 power_index;
666
667         if (enabled)
668                 power_index = IWM_POWER_INDEX_DEFAULT;
669         else
670                 power_index = IWM_POWER_INDEX_MIN;
671
672         if (power_index == iwm->conf.power_index)
673                 return 0;
674
675         iwm->conf.power_index = power_index;
676
677         return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
678                                        CFG_POWER_INDEX, iwm->conf.power_index);
679 }
680
681 static struct cfg80211_ops iwm_cfg80211_ops = {
682         .change_virtual_intf = iwm_cfg80211_change_iface,
683         .add_key = iwm_cfg80211_add_key,
684         .get_key = iwm_cfg80211_get_key,
685         .del_key = iwm_cfg80211_del_key,
686         .set_default_key = iwm_cfg80211_set_default_key,
687         .get_station = iwm_cfg80211_get_station,
688         .scan = iwm_cfg80211_scan,
689         .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
690         .connect = iwm_cfg80211_connect,
691         .disconnect = iwm_cfg80211_disconnect,
692         .join_ibss = iwm_cfg80211_join_ibss,
693         .leave_ibss = iwm_cfg80211_leave_ibss,
694         .set_tx_power = iwm_cfg80211_set_txpower,
695         .get_tx_power = iwm_cfg80211_get_txpower,
696         .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
697 };
698
699 static const u32 cipher_suites[] = {
700         WLAN_CIPHER_SUITE_WEP40,
701         WLAN_CIPHER_SUITE_WEP104,
702         WLAN_CIPHER_SUITE_TKIP,
703         WLAN_CIPHER_SUITE_CCMP,
704 };
705
706 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
707 {
708         int ret = 0;
709         struct wireless_dev *wdev;
710
711         /*
712          * We're trying to have the following memory
713          * layout:
714          *
715          * +-------------------------+
716          * | struct wiphy            |
717          * +-------------------------+
718          * | struct iwm_priv         |
719          * +-------------------------+
720          * | bus private data        |
721          * | (e.g. iwm_priv_sdio)    |
722          * +-------------------------+
723          *
724          */
725
726         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
727         if (!wdev) {
728                 dev_err(dev, "Couldn't allocate wireless device\n");
729                 return ERR_PTR(-ENOMEM);
730         }
731
732         wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
733                                 sizeof(struct iwm_priv) + sizeof_bus);
734         if (!wdev->wiphy) {
735                 dev_err(dev, "Couldn't allocate wiphy device\n");
736                 ret = -ENOMEM;
737                 goto out_err_new;
738         }
739
740         set_wiphy_dev(wdev->wiphy, dev);
741         wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
742         wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
743                                        BIT(NL80211_IFTYPE_ADHOC);
744         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
745         wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
746         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
747
748         wdev->wiphy->cipher_suites = cipher_suites;
749         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
750
751         ret = wiphy_register(wdev->wiphy);
752         if (ret < 0) {
753                 dev_err(dev, "Couldn't register wiphy device\n");
754                 goto out_err_register;
755         }
756
757         return wdev;
758
759  out_err_register:
760         wiphy_free(wdev->wiphy);
761
762  out_err_new:
763         kfree(wdev);
764
765         return ERR_PTR(ret);
766 }
767
768 void iwm_wdev_free(struct iwm_priv *iwm)
769 {
770         struct wireless_dev *wdev = iwm_to_wdev(iwm);
771
772         if (!wdev)
773                 return;
774
775         wiphy_unregister(wdev->wiphy);
776         wiphy_free(wdev->wiphy);
777         kfree(wdev);
778 }