blob: 739bd9b0ddea15ac63c55ec147ae3a50eee7cbae [file] [log] [blame]
Zhu Yibb9f8692009-05-21 21:20:45 +08001/*
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>
Samuel Ortiz13e0fe72009-06-15 21:59:52 +020026#include <linux/etherdevice.h>
Zhu Yibb9f8692009-05-21 21:20:45 +080027#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
61static 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
81static 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
98static 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
120static 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
127static 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
Samuel Ortiz13e0fe72009-06-15 21:59:52 +0200134static 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
161static 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
189static 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
235static 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
260static 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
277static 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
Zhu Yibb9f8692009-05-21 21:20:45 +0800301int 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
Johannes Berge36d56b2009-06-09 21:04:43 +0200338static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
339 struct net_device *ndev,
Zhu Yibb9f8692009-05-21 21:20:45 +0800340 enum nl80211_iftype type, u32 *flags,
341 struct vif_params *params)
342{
Zhu Yibb9f8692009-05-21 21:20:45 +0800343 struct wireless_dev *wdev;
344 struct iwm_priv *iwm;
345 u32 old_mode;
346
Zhu Yibb9f8692009-05-21 21:20:45 +0800347 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
378static 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
411static 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
Samuel Ortizb63b0ea2009-05-26 11:10:46 +0800434 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
Zhu Yibb9f8692009-05-21 21:20:45 +0800435 CFG_FRAG_THRESHOLD,
436 iwm->conf.frag_threshold);
437 if (ret < 0)
438 return ret;
439 }
440
441 return 0;
442}
443
444static 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
485static 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
495static struct cfg80211_ops iwm_cfg80211_ops = {
496 .change_virtual_intf = iwm_cfg80211_change_iface,
Samuel Ortiz13e0fe72009-06-15 21:59:52 +0200497 .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,
Zhu Yibb9f8692009-05-21 21:20:45 +0800501 .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
507struct 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
566void 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}