headers: remove sched.h from interrupt.h
[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/sched.h>
27 #include <linux/etherdevice.h>
28 #include <linux/wireless.h>
29 #include <linux/ieee80211.h>
30 #include <net/cfg80211.h>
31
32 #include "iwm.h"
33 #include "commands.h"
34 #include "cfg80211.h"
35 #include "debug.h"
36
37 #define RATETAB_ENT(_rate, _rateid, _flags) \
38         {                                                               \
39                 .bitrate        = (_rate),                              \
40                 .hw_value       = (_rateid),                            \
41                 .flags          = (_flags),                             \
42         }
43
44 #define CHAN2G(_channel, _freq, _flags) {                       \
45         .band                   = IEEE80211_BAND_2GHZ,          \
46         .center_freq            = (_freq),                      \
47         .hw_value               = (_channel),                   \
48         .flags                  = (_flags),                     \
49         .max_antenna_gain       = 0,                            \
50         .max_power              = 30,                           \
51 }
52
53 #define CHAN5G(_channel, _flags) {                              \
54         .band                   = IEEE80211_BAND_5GHZ,          \
55         .center_freq            = 5000 + (5 * (_channel)),      \
56         .hw_value               = (_channel),                   \
57         .flags                  = (_flags),                     \
58         .max_antenna_gain       = 0,                            \
59         .max_power              = 30,                           \
60 }
61
62 static struct ieee80211_rate iwm_rates[] = {
63         RATETAB_ENT(10,  0x1,   0),
64         RATETAB_ENT(20,  0x2,   0),
65         RATETAB_ENT(55,  0x4,   0),
66         RATETAB_ENT(110, 0x8,   0),
67         RATETAB_ENT(60,  0x10,  0),
68         RATETAB_ENT(90,  0x20,  0),
69         RATETAB_ENT(120, 0x40,  0),
70         RATETAB_ENT(180, 0x80,  0),
71         RATETAB_ENT(240, 0x100, 0),
72         RATETAB_ENT(360, 0x200, 0),
73         RATETAB_ENT(480, 0x400, 0),
74         RATETAB_ENT(540, 0x800, 0),
75 };
76
77 #define iwm_a_rates             (iwm_rates + 4)
78 #define iwm_a_rates_size        8
79 #define iwm_g_rates             (iwm_rates + 0)
80 #define iwm_g_rates_size        12
81
82 static struct ieee80211_channel iwm_2ghz_channels[] = {
83         CHAN2G(1, 2412, 0),
84         CHAN2G(2, 2417, 0),
85         CHAN2G(3, 2422, 0),
86         CHAN2G(4, 2427, 0),
87         CHAN2G(5, 2432, 0),
88         CHAN2G(6, 2437, 0),
89         CHAN2G(7, 2442, 0),
90         CHAN2G(8, 2447, 0),
91         CHAN2G(9, 2452, 0),
92         CHAN2G(10, 2457, 0),
93         CHAN2G(11, 2462, 0),
94         CHAN2G(12, 2467, 0),
95         CHAN2G(13, 2472, 0),
96         CHAN2G(14, 2484, 0),
97 };
98
99 static struct ieee80211_channel iwm_5ghz_a_channels[] = {
100         CHAN5G(34, 0),          CHAN5G(36, 0),
101         CHAN5G(38, 0),          CHAN5G(40, 0),
102         CHAN5G(42, 0),          CHAN5G(44, 0),
103         CHAN5G(46, 0),          CHAN5G(48, 0),
104         CHAN5G(52, 0),          CHAN5G(56, 0),
105         CHAN5G(60, 0),          CHAN5G(64, 0),
106         CHAN5G(100, 0),         CHAN5G(104, 0),
107         CHAN5G(108, 0),         CHAN5G(112, 0),
108         CHAN5G(116, 0),         CHAN5G(120, 0),
109         CHAN5G(124, 0),         CHAN5G(128, 0),
110         CHAN5G(132, 0),         CHAN5G(136, 0),
111         CHAN5G(140, 0),         CHAN5G(149, 0),
112         CHAN5G(153, 0),         CHAN5G(157, 0),
113         CHAN5G(161, 0),         CHAN5G(165, 0),
114         CHAN5G(184, 0),         CHAN5G(188, 0),
115         CHAN5G(192, 0),         CHAN5G(196, 0),
116         CHAN5G(200, 0),         CHAN5G(204, 0),
117         CHAN5G(208, 0),         CHAN5G(212, 0),
118         CHAN5G(216, 0),
119 };
120
121 static struct ieee80211_supported_band iwm_band_2ghz = {
122         .channels = iwm_2ghz_channels,
123         .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
124         .bitrates = iwm_g_rates,
125         .n_bitrates = iwm_g_rates_size,
126 };
127
128 static struct ieee80211_supported_band iwm_band_5ghz = {
129         .channels = iwm_5ghz_a_channels,
130         .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
131         .bitrates = iwm_a_rates,
132         .n_bitrates = iwm_a_rates_size,
133 };
134
135 static int iwm_key_init(struct iwm_key *key, u8 key_index,
136                         const u8 *mac_addr, struct key_params *params)
137 {
138         key->hdr.key_idx = key_index;
139         if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
140                 key->hdr.multicast = 1;
141                 memset(key->hdr.mac, 0xff, ETH_ALEN);
142         } else {
143                 key->hdr.multicast = 0;
144                 memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
145         }
146
147         if (params) {
148                 if (params->key_len > WLAN_MAX_KEY_LEN ||
149                     params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
150                         return -EINVAL;
151
152                 key->cipher = params->cipher;
153                 key->key_len = params->key_len;
154                 key->seq_len = params->seq_len;
155                 memcpy(key->key, params->key, key->key_len);
156                 memcpy(key->seq, params->seq, key->seq_len);
157         }
158
159         return 0;
160 }
161
162 static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
163                                 u8 key_index, const u8 *mac_addr,
164                                 struct key_params *params)
165 {
166         struct iwm_priv *iwm = ndev_to_iwm(ndev);
167         struct iwm_key *key = &iwm->keys[key_index];
168         int ret;
169
170         IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
171
172         memset(key, 0, sizeof(struct iwm_key));
173         ret = iwm_key_init(key, key_index, mac_addr, params);
174         if (ret < 0) {
175                 IWM_ERR(iwm, "Invalid key_params\n");
176                 return ret;
177         }
178
179         return iwm_set_key(iwm, 0, key);
180 }
181
182 static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
183                                 u8 key_index, const u8 *mac_addr, void *cookie,
184                                 void (*callback)(void *cookie,
185                                                  struct key_params*))
186 {
187         struct iwm_priv *iwm = ndev_to_iwm(ndev);
188         struct iwm_key *key = &iwm->keys[key_index];
189         struct key_params params;
190
191         IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
192
193         memset(&params, 0, sizeof(params));
194
195         params.cipher = key->cipher;
196         params.key_len = key->key_len;
197         params.seq_len = key->seq_len;
198         params.seq = key->seq;
199         params.key = key->key;
200
201         callback(cookie, &params);
202
203         return key->key_len ? 0 : -ENOENT;
204 }
205
206
207 static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
208                                 u8 key_index, const u8 *mac_addr)
209 {
210         struct iwm_priv *iwm = ndev_to_iwm(ndev);
211         struct iwm_key *key = &iwm->keys[key_index];
212
213         if (!iwm->keys[key_index].key_len) {
214                 IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
215                 return 0;
216         }
217
218         if (key_index == iwm->default_key)
219                 iwm->default_key = -1;
220
221         return iwm_set_key(iwm, 1, key);
222 }
223
224 static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
225                                         struct net_device *ndev,
226                                         u8 key_index)
227 {
228         struct iwm_priv *iwm = ndev_to_iwm(ndev);
229
230         IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
231
232         if (!iwm->keys[key_index].key_len) {
233                 IWM_ERR(iwm, "Key %d not used\n", key_index);
234                 return -EINVAL;
235         }
236
237         iwm->default_key = key_index;
238
239         return iwm_set_tx_key(iwm, key_index);
240 }
241
242 static int iwm_cfg80211_get_station(struct wiphy *wiphy,
243                                     struct net_device *ndev,
244                                     u8 *mac, struct station_info *sinfo)
245 {
246         struct iwm_priv *iwm = ndev_to_iwm(ndev);
247
248         if (memcmp(mac, iwm->bssid, ETH_ALEN))
249                 return -ENOENT;
250
251         sinfo->filled |= STATION_INFO_TX_BITRATE;
252         sinfo->txrate.legacy = iwm->rate * 10;
253
254         if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
255                 sinfo->filled |= STATION_INFO_SIGNAL;
256                 sinfo->signal = iwm->wstats.qual.level;
257         }
258
259         return 0;
260 }
261
262
263 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
264 {
265         struct wiphy *wiphy = iwm_to_wiphy(iwm);
266         struct iwm_bss_info *bss, *next;
267         struct iwm_umac_notif_bss_info *umac_bss;
268         struct ieee80211_mgmt *mgmt;
269         struct ieee80211_channel *channel;
270         struct ieee80211_supported_band *band;
271         s32 signal;
272         int freq;
273
274         list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
275                 umac_bss = bss->bss;
276                 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
277
278                 if (umac_bss->band == UMAC_BAND_2GHZ)
279                         band = wiphy->bands[IEEE80211_BAND_2GHZ];
280                 else if (umac_bss->band == UMAC_BAND_5GHZ)
281                         band = wiphy->bands[IEEE80211_BAND_5GHZ];
282                 else {
283                         IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
284                         return -EINVAL;
285                 }
286
287                 freq = ieee80211_channel_to_frequency(umac_bss->channel);
288                 channel = ieee80211_get_channel(wiphy, freq);
289                 signal = umac_bss->rssi * 100;
290
291                 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
292                                                le16_to_cpu(umac_bss->frame_len),
293                                                signal, GFP_KERNEL))
294                         return -EINVAL;
295         }
296
297         return 0;
298 }
299
300 static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
301                                      struct net_device *ndev,
302                                      enum nl80211_iftype type, u32 *flags,
303                                      struct vif_params *params)
304 {
305         struct wireless_dev *wdev;
306         struct iwm_priv *iwm;
307         u32 old_mode;
308
309         wdev = ndev->ieee80211_ptr;
310         iwm = ndev_to_iwm(ndev);
311         old_mode = iwm->conf.mode;
312
313         switch (type) {
314         case NL80211_IFTYPE_STATION:
315                 iwm->conf.mode = UMAC_MODE_BSS;
316                 break;
317         case NL80211_IFTYPE_ADHOC:
318                 iwm->conf.mode = UMAC_MODE_IBSS;
319                 break;
320         default:
321                 return -EOPNOTSUPP;
322         }
323
324         wdev->iftype = type;
325
326         if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
327                 return 0;
328
329         iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
330
331         if (iwm->umac_profile_active)
332                 iwm_invalidate_mlme_profile(iwm);
333
334         return 0;
335 }
336
337 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
338                              struct cfg80211_scan_request *request)
339 {
340         struct iwm_priv *iwm = ndev_to_iwm(ndev);
341         int ret;
342
343         if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
344                 IWM_ERR(iwm, "Scan while device is not ready\n");
345                 return -EIO;
346         }
347
348         if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
349                 IWM_ERR(iwm, "Scanning already\n");
350                 return -EAGAIN;
351         }
352
353         if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
354                 IWM_ERR(iwm, "Scanning being aborted\n");
355                 return -EAGAIN;
356         }
357
358         set_bit(IWM_STATUS_SCANNING, &iwm->status);
359
360         ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
361         if (ret) {
362                 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
363                 return ret;
364         }
365
366         iwm->scan_request = request;
367         return 0;
368 }
369
370 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
371 {
372         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
373
374         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
375             (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
376                 int ret;
377
378                 iwm->conf.rts_threshold = wiphy->rts_threshold;
379
380                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
381                                              CFG_RTS_THRESHOLD,
382                                              iwm->conf.rts_threshold);
383                 if (ret < 0)
384                         return ret;
385         }
386
387         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
388             (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
389                 int ret;
390
391                 iwm->conf.frag_threshold = wiphy->frag_threshold;
392
393                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
394                                              CFG_FRAG_THRESHOLD,
395                                              iwm->conf.frag_threshold);
396                 if (ret < 0)
397                         return ret;
398         }
399
400         return 0;
401 }
402
403 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
404                                   struct cfg80211_ibss_params *params)
405 {
406         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
407         struct ieee80211_channel *chan = params->channel;
408         struct cfg80211_bss *bss;
409
410         if (!test_bit(IWM_STATUS_READY, &iwm->status))
411                 return -EIO;
412
413         /* UMAC doesn't support creating IBSS network with specified bssid.
414          * This should be removed after we have join only mode supported. */
415         if (params->bssid)
416                 return -EOPNOTSUPP;
417
418         bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
419                                 params->ssid, params->ssid_len);
420         if (!bss) {
421                 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
422                 schedule_timeout_interruptible(2 * HZ);
423                 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
424                                         params->ssid, params->ssid_len);
425         }
426         /* IBSS join only mode is not supported by UMAC ATM */
427         if (bss) {
428                 cfg80211_put_bss(bss);
429                 return -EOPNOTSUPP;
430         }
431
432         iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
433         iwm->umac_profile->ibss.band = chan->band;
434         iwm->umac_profile->ibss.channel = iwm->channel;
435         iwm->umac_profile->ssid.ssid_len = params->ssid_len;
436         memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
437
438         if (params->bssid)
439                 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
440
441         return iwm_send_mlme_profile(iwm);
442 }
443
444 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
445 {
446         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
447
448         if (iwm->umac_profile_active)
449                 return iwm_invalidate_mlme_profile(iwm);
450
451         return 0;
452 }
453
454 static int iwm_set_auth_type(struct iwm_priv *iwm,
455                              enum nl80211_auth_type sme_auth_type)
456 {
457         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
458
459         switch (sme_auth_type) {
460         case NL80211_AUTHTYPE_AUTOMATIC:
461         case NL80211_AUTHTYPE_OPEN_SYSTEM:
462                 IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n");
463                 *auth_type = UMAC_AUTH_TYPE_OPEN;
464                 break;
465         case NL80211_AUTHTYPE_SHARED_KEY:
466                 if (iwm->umac_profile->sec.flags &
467                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
468                         IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n");
469                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
470                 } else {
471                         IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n");
472                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
473                 }
474
475                 break;
476         default:
477                 IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type);
478                 return -ENOTSUPP;
479         }
480
481         return 0;
482 }
483
484 static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
485 {
486         IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version);
487
488         if (!wpa_version) {
489                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
490                 return 0;
491         }
492
493         if (wpa_version & NL80211_WPA_VERSION_2)
494                 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
495
496         if (wpa_version & NL80211_WPA_VERSION_1)
497                 iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
498
499         return 0;
500 }
501
502 static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast)
503 {
504         u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
505                 &iwm->umac_profile->sec.mcast_cipher;
506
507         if (!cipher) {
508                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
509                 return 0;
510         }
511
512         IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm',
513                      cipher);
514
515         switch (cipher) {
516         case IW_AUTH_CIPHER_NONE:
517                 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
518                 break;
519         case WLAN_CIPHER_SUITE_WEP40:
520                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
521                 break;
522         case WLAN_CIPHER_SUITE_WEP104:
523                 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
524                 break;
525         case WLAN_CIPHER_SUITE_TKIP:
526                 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
527                 break;
528         case WLAN_CIPHER_SUITE_CCMP:
529                 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
530                 break;
531         default:
532                 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
533                 return -ENOTSUPP;
534         }
535
536         return 0;
537 }
538
539 static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt)
540 {
541         u8 *auth_type = &iwm->umac_profile->sec.auth_type;
542
543         IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt);
544
545         if (key_mgt == WLAN_AKM_SUITE_8021X)
546                 *auth_type = UMAC_AUTH_TYPE_8021X;
547         else if (key_mgt == WLAN_AKM_SUITE_PSK) {
548                 if (iwm->umac_profile->sec.flags &
549                     (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
550                         *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
551                 else
552                         *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
553         } else {
554                 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
555                 return -EINVAL;
556         }
557
558         return 0;
559 }
560
561
562 static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
563                                  struct cfg80211_connect_params *sme)
564 {
565         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
566         struct ieee80211_channel *chan = sme->channel;
567         struct key_params key_param;
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 (iwm->umac_profile_active) {
577                 ret = iwm_invalidate_mlme_profile(iwm);
578                 if (ret) {
579                         IWM_ERR(iwm, "Couldn't invalidate profile\n");
580                         return ret;
581                 }
582         }
583
584         if (chan)
585                 iwm->channel =
586                         ieee80211_frequency_to_channel(chan->center_freq);
587
588         iwm->umac_profile->ssid.ssid_len = sme->ssid_len;
589         memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len);
590
591         if (sme->bssid) {
592                 IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid);
593                 memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN);
594                 iwm->umac_profile->bss_num = 1;
595         } else {
596                 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
597                 iwm->umac_profile->bss_num = 0;
598         }
599
600         ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions);
601         if (ret < 0)
602                 return ret;
603
604         ret = iwm_set_auth_type(iwm, sme->auth_type);
605         if (ret < 0)
606                 return ret;
607
608         if (sme->crypto.n_ciphers_pairwise) {
609                 ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0],
610                                      true);
611                 if (ret < 0)
612                         return ret;
613         }
614
615         ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false);
616         if (ret < 0)
617                 return ret;
618
619         if (sme->crypto.n_akm_suites) {
620                 ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]);
621                 if (ret < 0)
622                         return ret;
623         }
624
625         /*
626          * We save the WEP key in case we want to do shared authentication.
627          * We have to do it so because UMAC will assert whenever it gets a
628          * key before a profile.
629          */
630         if (sme->key) {
631                 key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
632                 if (key_param.key == NULL)
633                         return -ENOMEM;
634                 key_param.key_len = sme->key_len;
635                 key_param.seq_len = 0;
636                 key_param.cipher = sme->crypto.ciphers_pairwise[0];
637
638                 ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
639                                    NULL, &key_param);
640                 kfree(key_param.key);
641                 if (ret < 0) {
642                         IWM_ERR(iwm, "Invalid key_params\n");
643                         return ret;
644                 }
645
646                 iwm->default_key = sme->key_idx;
647         }
648
649         ret = iwm_send_mlme_profile(iwm);
650
651         if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
652             sme->key == NULL)
653                 return ret;
654
655         /*
656          * We want to do shared auth.
657          * We need to actually set the key we previously cached,
658          * and then tell the UMAC it's the default one.
659          * That will trigger the auth+assoc UMAC machinery, and again,
660          * this must be done after setting the profile.
661          */
662         ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
663         if (ret < 0)
664                 return ret;
665
666         return iwm_set_tx_key(iwm, iwm->default_key);
667 }
668
669 static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
670                                    u16 reason_code)
671 {
672         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
673
674         IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
675
676         if (iwm->umac_profile_active)
677                 iwm_invalidate_mlme_profile(iwm);
678
679         return 0;
680 }
681
682 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
683                                     enum tx_power_setting type, int dbm)
684 {
685         switch (type) {
686         case TX_POWER_AUTOMATIC:
687                 return 0;
688         default:
689                 return -EOPNOTSUPP;
690         }
691
692         return 0;
693 }
694
695 static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
696 {
697         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
698
699         *dbm = iwm->txpower;
700
701         return 0;
702 }
703
704 static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
705                                        struct net_device *dev,
706                                        bool enabled, int timeout)
707 {
708         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
709         u32 power_index;
710
711         if (enabled)
712                 power_index = IWM_POWER_INDEX_DEFAULT;
713         else
714                 power_index = IWM_POWER_INDEX_MIN;
715
716         if (power_index == iwm->conf.power_index)
717                 return 0;
718
719         iwm->conf.power_index = power_index;
720
721         return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
722                                        CFG_POWER_INDEX, iwm->conf.power_index);
723 }
724
725 static struct cfg80211_ops iwm_cfg80211_ops = {
726         .change_virtual_intf = iwm_cfg80211_change_iface,
727         .add_key = iwm_cfg80211_add_key,
728         .get_key = iwm_cfg80211_get_key,
729         .del_key = iwm_cfg80211_del_key,
730         .set_default_key = iwm_cfg80211_set_default_key,
731         .get_station = iwm_cfg80211_get_station,
732         .scan = iwm_cfg80211_scan,
733         .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
734         .connect = iwm_cfg80211_connect,
735         .disconnect = iwm_cfg80211_disconnect,
736         .join_ibss = iwm_cfg80211_join_ibss,
737         .leave_ibss = iwm_cfg80211_leave_ibss,
738         .set_tx_power = iwm_cfg80211_set_txpower,
739         .get_tx_power = iwm_cfg80211_get_txpower,
740         .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
741 };
742
743 static const u32 cipher_suites[] = {
744         WLAN_CIPHER_SUITE_WEP40,
745         WLAN_CIPHER_SUITE_WEP104,
746         WLAN_CIPHER_SUITE_TKIP,
747         WLAN_CIPHER_SUITE_CCMP,
748 };
749
750 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
751 {
752         int ret = 0;
753         struct wireless_dev *wdev;
754
755         /*
756          * We're trying to have the following memory
757          * layout:
758          *
759          * +-------------------------+
760          * | struct wiphy            |
761          * +-------------------------+
762          * | struct iwm_priv         |
763          * +-------------------------+
764          * | bus private data        |
765          * | (e.g. iwm_priv_sdio)    |
766          * +-------------------------+
767          *
768          */
769
770         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
771         if (!wdev) {
772                 dev_err(dev, "Couldn't allocate wireless device\n");
773                 return ERR_PTR(-ENOMEM);
774         }
775
776         wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
777                                 sizeof(struct iwm_priv) + sizeof_bus);
778         if (!wdev->wiphy) {
779                 dev_err(dev, "Couldn't allocate wiphy device\n");
780                 ret = -ENOMEM;
781                 goto out_err_new;
782         }
783
784         set_wiphy_dev(wdev->wiphy, dev);
785         wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
786         wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
787                                        BIT(NL80211_IFTYPE_ADHOC);
788         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
789         wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
790         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
791
792         wdev->wiphy->cipher_suites = cipher_suites;
793         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
794
795         ret = wiphy_register(wdev->wiphy);
796         if (ret < 0) {
797                 dev_err(dev, "Couldn't register wiphy device\n");
798                 goto out_err_register;
799         }
800
801         return wdev;
802
803  out_err_register:
804         wiphy_free(wdev->wiphy);
805
806  out_err_new:
807         kfree(wdev);
808
809         return ERR_PTR(ret);
810 }
811
812 void iwm_wdev_free(struct iwm_priv *iwm)
813 {
814         struct wireless_dev *wdev = iwm_to_wdev(iwm);
815
816         if (!wdev)
817                 return;
818
819         wiphy_unregister(wdev->wiphy);
820         wiphy_free(wdev->wiphy);
821         kfree(wdev);
822 }