iwmc3200wifi: cfg80211 key hooks implemetation
[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         return iwm_set_key(iwm, 1, key);
275 }
276
277 static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
278                                         struct net_device *ndev,
279                                         u8 key_index)
280 {
281         struct iwm_priv *iwm = ndev_to_iwm(ndev);
282         int ret;
283
284         IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
285
286         if (!iwm->keys[key_index].key_len) {
287                 IWM_ERR(iwm, "Key %d not used\n", key_index);
288                 return -EINVAL;
289         }
290
291         ret = iwm_set_tx_key(iwm, key_index);
292         if (ret < 0)
293                 return ret;
294
295         iwm->default_key = key_index;
296
297         return iwm_reset_profile(iwm);
298 }
299
300
301 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
302 {
303         struct wiphy *wiphy = iwm_to_wiphy(iwm);
304         struct iwm_bss_info *bss, *next;
305         struct iwm_umac_notif_bss_info *umac_bss;
306         struct ieee80211_mgmt *mgmt;
307         struct ieee80211_channel *channel;
308         struct ieee80211_supported_band *band;
309         s32 signal;
310         int freq;
311
312         list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
313                 umac_bss = bss->bss;
314                 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
315
316                 if (umac_bss->band == UMAC_BAND_2GHZ)
317                         band = wiphy->bands[IEEE80211_BAND_2GHZ];
318                 else if (umac_bss->band == UMAC_BAND_5GHZ)
319                         band = wiphy->bands[IEEE80211_BAND_5GHZ];
320                 else {
321                         IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
322                         return -EINVAL;
323                 }
324
325                 freq = ieee80211_channel_to_frequency(umac_bss->channel);
326                 channel = ieee80211_get_channel(wiphy, freq);
327                 signal = umac_bss->rssi * 100;
328
329                 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
330                                                le16_to_cpu(umac_bss->frame_len),
331                                                signal, GFP_KERNEL))
332                         return -EINVAL;
333         }
334
335         return 0;
336 }
337
338 static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
339                                      struct net_device *ndev,
340                                      enum nl80211_iftype type, u32 *flags,
341                                      struct vif_params *params)
342 {
343         struct wireless_dev *wdev;
344         struct iwm_priv *iwm;
345         u32 old_mode;
346
347         wdev = ndev->ieee80211_ptr;
348         iwm = ndev_to_iwm(ndev);
349         old_mode = iwm->conf.mode;
350
351         switch (type) {
352         case NL80211_IFTYPE_STATION:
353                 iwm->conf.mode = UMAC_MODE_BSS;
354                 break;
355         case NL80211_IFTYPE_ADHOC:
356                 iwm->conf.mode = UMAC_MODE_IBSS;
357                 break;
358         default:
359                 return -EOPNOTSUPP;
360         }
361
362         wdev->iftype = type;
363
364         if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
365                 return 0;
366
367         iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
368
369         if (iwm->umac_profile_active) {
370                 int ret = iwm_invalidate_mlme_profile(iwm);
371                 if (ret < 0)
372                         IWM_ERR(iwm, "Couldn't invalidate profile\n");
373         }
374
375         return 0;
376 }
377
378 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
379                              struct cfg80211_scan_request *request)
380 {
381         struct iwm_priv *iwm = ndev_to_iwm(ndev);
382         int ret;
383
384         if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
385                 IWM_ERR(iwm, "Scan while device is not ready\n");
386                 return -EIO;
387         }
388
389         if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
390                 IWM_ERR(iwm, "Scanning already\n");
391                 return -EAGAIN;
392         }
393
394         if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
395                 IWM_ERR(iwm, "Scanning being aborted\n");
396                 return -EAGAIN;
397         }
398
399         set_bit(IWM_STATUS_SCANNING, &iwm->status);
400
401         ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
402         if (ret) {
403                 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
404                 return ret;
405         }
406
407         iwm->scan_request = request;
408         return 0;
409 }
410
411 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
412 {
413         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
414
415         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
416             (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
417                 int ret;
418
419                 iwm->conf.rts_threshold = wiphy->rts_threshold;
420
421                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
422                                              CFG_RTS_THRESHOLD,
423                                              iwm->conf.rts_threshold);
424                 if (ret < 0)
425                         return ret;
426         }
427
428         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
429             (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
430                 int ret;
431
432                 iwm->conf.frag_threshold = wiphy->frag_threshold;
433
434                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
435                                              CFG_FRAG_THRESHOLD,
436                                              iwm->conf.frag_threshold);
437                 if (ret < 0)
438                         return ret;
439         }
440
441         return 0;
442 }
443
444 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
445                                   struct cfg80211_ibss_params *params)
446 {
447         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
448         struct ieee80211_channel *chan = params->channel;
449         struct cfg80211_bss *bss;
450
451         if (!test_bit(IWM_STATUS_READY, &iwm->status))
452                 return -EIO;
453
454         /* UMAC doesn't support creating IBSS network with specified bssid.
455          * This should be removed after we have join only mode supported. */
456         if (params->bssid)
457                 return -EOPNOTSUPP;
458
459         bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
460                                 params->ssid, params->ssid_len);
461         if (!bss) {
462                 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
463                 schedule_timeout_interruptible(2 * HZ);
464                 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
465                                         params->ssid, params->ssid_len);
466         }
467         /* IBSS join only mode is not supported by UMAC ATM */
468         if (bss) {
469                 cfg80211_put_bss(bss);
470                 return -EOPNOTSUPP;
471         }
472
473         iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
474         iwm->umac_profile->ibss.band = chan->band;
475         iwm->umac_profile->ibss.channel = iwm->channel;
476         iwm->umac_profile->ssid.ssid_len = params->ssid_len;
477         memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
478
479         if (params->bssid)
480                 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
481
482         return iwm_send_mlme_profile(iwm);
483 }
484
485 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
486 {
487         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
488
489         if (iwm->umac_profile_active)
490                 return iwm_invalidate_mlme_profile(iwm);
491
492         return 0;
493 }
494
495 static struct cfg80211_ops iwm_cfg80211_ops = {
496         .change_virtual_intf = iwm_cfg80211_change_iface,
497         .add_key = iwm_cfg80211_add_key,
498         .get_key = iwm_cfg80211_get_key,
499         .del_key = iwm_cfg80211_del_key,
500         .set_default_key = iwm_cfg80211_set_default_key,
501         .scan = iwm_cfg80211_scan,
502         .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
503         .join_ibss = iwm_cfg80211_join_ibss,
504         .leave_ibss = iwm_cfg80211_leave_ibss,
505 };
506
507 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
508 {
509         int ret = 0;
510         struct wireless_dev *wdev;
511
512         /*
513          * We're trying to have the following memory
514          * layout:
515          *
516          * +-------------------------+
517          * | struct wiphy            |
518          * +-------------------------+
519          * | struct iwm_priv         |
520          * +-------------------------+
521          * | bus private data        |
522          * | (e.g. iwm_priv_sdio)    |
523          * +-------------------------+
524          *
525          */
526
527         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
528         if (!wdev) {
529                 dev_err(dev, "Couldn't allocate wireless device\n");
530                 return ERR_PTR(-ENOMEM);
531         }
532
533         wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
534                                 sizeof(struct iwm_priv) + sizeof_bus);
535         if (!wdev->wiphy) {
536                 dev_err(dev, "Couldn't allocate wiphy device\n");
537                 ret = -ENOMEM;
538                 goto out_err_new;
539         }
540
541         set_wiphy_dev(wdev->wiphy, dev);
542         wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
543         wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
544                                        BIT(NL80211_IFTYPE_ADHOC);
545         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
546         wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
547         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
548
549         ret = wiphy_register(wdev->wiphy);
550         if (ret < 0) {
551                 dev_err(dev, "Couldn't register wiphy device\n");
552                 goto out_err_register;
553         }
554
555         return wdev;
556
557  out_err_register:
558         wiphy_free(wdev->wiphy);
559
560  out_err_new:
561         kfree(wdev);
562
563         return ERR_PTR(ret);
564 }
565
566 void iwm_wdev_free(struct iwm_priv *iwm)
567 {
568         struct wireless_dev *wdev = iwm_to_wdev(iwm);
569
570         if (!wdev)
571                 return;
572
573         wiphy_unregister(wdev->wiphy);
574         wiphy_free(wdev->wiphy);
575         kfree(wdev);
576 }