2 * Intel Wireless Multicomm 3200 WiFi driver
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
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.
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.
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
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>
36 #define RATETAB_ENT(_rate, _rateid, _flags) \
39 .hw_value = (_rateid), \
43 #define CHAN2G(_channel, _freq, _flags) { \
44 .band = IEEE80211_BAND_2GHZ, \
45 .center_freq = (_freq), \
46 .hw_value = (_channel), \
48 .max_antenna_gain = 0, \
52 #define CHAN5G(_channel, _flags) { \
53 .band = IEEE80211_BAND_5GHZ, \
54 .center_freq = 5000 + (5 * (_channel)), \
55 .hw_value = (_channel), \
57 .max_antenna_gain = 0, \
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),
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
81 static struct ieee80211_channel iwm_2ghz_channels[] = {
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),
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,
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,
134 static int iwm_key_init(struct iwm_key *key, u8 key_index,
135 const u8 *mac_addr, struct key_params *params)
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);
142 key->hdr.multicast = 0;
143 memcpy(key->hdr.mac, mac_addr, ETH_ALEN);
147 if (params->key_len > WLAN_MAX_KEY_LEN ||
148 params->seq_len > IW_ENCODE_SEQ_MAX_SIZE)
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);
161 static int iwm_reset_profile(struct iwm_priv *iwm)
165 if (!iwm->umac_profile_active)
169 * If there is a current active profile, but no
170 * default key, it's not worth trying to associate again.
172 if (iwm->default_key < 0)
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.
180 ret = iwm_invalidate_mlme_profile(iwm);
182 IWM_ERR(iwm, "Couldn't invalidate profile\n");
186 return iwm_send_mlme_profile(iwm);
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)
193 struct iwm_priv *iwm = ndev_to_iwm(ndev);
194 struct iwm_key *key = &iwm->keys[key_index];
197 IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
199 memset(key, 0, sizeof(struct iwm_key));
200 ret = iwm_key_init(key, key_index, mac_addr, params);
202 IWM_ERR(iwm, "Invalid key_params\n");
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
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;
221 IWM_DBG_WEXT(iwm, DBG, "WEP key\n");
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;
229 return iwm_reset_profile(iwm);
232 return iwm_set_key(iwm, 0, key);
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,
240 struct iwm_priv *iwm = ndev_to_iwm(ndev);
241 struct iwm_key *key = &iwm->keys[key_index];
242 struct key_params params;
244 IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index);
246 memset(¶ms, 0, sizeof(params));
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;
254 callback(cookie, ¶ms);
256 return key->key_len ? 0 : -ENOENT;
260 static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
261 u8 key_index, const u8 *mac_addr)
263 struct iwm_priv *iwm = ndev_to_iwm(ndev);
264 struct iwm_key *key = &iwm->keys[key_index];
266 if (!iwm->keys[key_index].key_len) {
267 IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
271 if (key_index == iwm->default_key)
272 iwm->default_key = -1;
274 /* If the interface is down, we just cache this */
275 if (!test_bit(IWM_STATUS_READY, &iwm->status))
278 return iwm_set_key(iwm, 1, key);
281 static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
282 struct net_device *ndev,
285 struct iwm_priv *iwm = ndev_to_iwm(ndev);
288 IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
290 if (!iwm->keys[key_index].key_len) {
291 IWM_ERR(iwm, "Key %d not used\n", key_index);
295 iwm->default_key = key_index;
297 /* If the interface is down, we just cache this */
298 if (!test_bit(IWM_STATUS_READY, &iwm->status))
301 ret = iwm_set_tx_key(iwm, key_index);
305 return iwm_reset_profile(iwm);
309 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
311 struct wiphy *wiphy = iwm_to_wiphy(iwm);
312 struct iwm_bss_info *bss, *next;
313 struct iwm_umac_notif_bss_info *umac_bss;
314 struct ieee80211_mgmt *mgmt;
315 struct ieee80211_channel *channel;
316 struct ieee80211_supported_band *band;
320 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
322 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
324 if (umac_bss->band == UMAC_BAND_2GHZ)
325 band = wiphy->bands[IEEE80211_BAND_2GHZ];
326 else if (umac_bss->band == UMAC_BAND_5GHZ)
327 band = wiphy->bands[IEEE80211_BAND_5GHZ];
329 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
333 freq = ieee80211_channel_to_frequency(umac_bss->channel);
334 channel = ieee80211_get_channel(wiphy, freq);
335 signal = umac_bss->rssi * 100;
337 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
338 le16_to_cpu(umac_bss->frame_len),
346 static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
347 struct net_device *ndev,
348 enum nl80211_iftype type, u32 *flags,
349 struct vif_params *params)
351 struct wireless_dev *wdev;
352 struct iwm_priv *iwm;
355 wdev = ndev->ieee80211_ptr;
356 iwm = ndev_to_iwm(ndev);
357 old_mode = iwm->conf.mode;
360 case NL80211_IFTYPE_STATION:
361 iwm->conf.mode = UMAC_MODE_BSS;
363 case NL80211_IFTYPE_ADHOC:
364 iwm->conf.mode = UMAC_MODE_IBSS;
372 if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
375 iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
377 if (iwm->umac_profile_active) {
378 int ret = iwm_invalidate_mlme_profile(iwm);
380 IWM_ERR(iwm, "Couldn't invalidate profile\n");
386 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
387 struct cfg80211_scan_request *request)
389 struct iwm_priv *iwm = ndev_to_iwm(ndev);
392 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
393 IWM_ERR(iwm, "Scan while device is not ready\n");
397 if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
398 IWM_ERR(iwm, "Scanning already\n");
402 if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
403 IWM_ERR(iwm, "Scanning being aborted\n");
407 set_bit(IWM_STATUS_SCANNING, &iwm->status);
409 ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
411 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
415 iwm->scan_request = request;
419 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
421 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
423 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
424 (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
427 iwm->conf.rts_threshold = wiphy->rts_threshold;
429 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
431 iwm->conf.rts_threshold);
436 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
437 (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
440 iwm->conf.frag_threshold = wiphy->frag_threshold;
442 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
444 iwm->conf.frag_threshold);
452 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
453 struct cfg80211_ibss_params *params)
455 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
456 struct ieee80211_channel *chan = params->channel;
457 struct cfg80211_bss *bss;
459 if (!test_bit(IWM_STATUS_READY, &iwm->status))
462 /* UMAC doesn't support creating IBSS network with specified bssid.
463 * This should be removed after we have join only mode supported. */
467 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
468 params->ssid, params->ssid_len);
470 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
471 schedule_timeout_interruptible(2 * HZ);
472 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
473 params->ssid, params->ssid_len);
475 /* IBSS join only mode is not supported by UMAC ATM */
477 cfg80211_put_bss(bss);
481 iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
482 iwm->umac_profile->ibss.band = chan->band;
483 iwm->umac_profile->ibss.channel = iwm->channel;
484 iwm->umac_profile->ssid.ssid_len = params->ssid_len;
485 memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
488 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
490 return iwm_send_mlme_profile(iwm);
493 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
495 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
497 if (iwm->umac_profile_active)
498 return iwm_invalidate_mlme_profile(iwm);
503 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
504 enum tx_power_setting type, int dbm)
507 case TX_POWER_AUTOMATIC:
516 static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
518 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
525 static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
526 struct net_device *dev,
527 bool enabled, int timeout)
529 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
533 power_index = IWM_POWER_INDEX_DEFAULT;
535 power_index = IWM_POWER_INDEX_MIN;
537 if (power_index == iwm->conf.power_index)
540 iwm->conf.power_index = power_index;
542 return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
543 CFG_POWER_INDEX, iwm->conf.power_index);
546 static struct cfg80211_ops iwm_cfg80211_ops = {
547 .change_virtual_intf = iwm_cfg80211_change_iface,
548 .add_key = iwm_cfg80211_add_key,
549 .get_key = iwm_cfg80211_get_key,
550 .del_key = iwm_cfg80211_del_key,
551 .set_default_key = iwm_cfg80211_set_default_key,
552 .scan = iwm_cfg80211_scan,
553 .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
554 .join_ibss = iwm_cfg80211_join_ibss,
555 .leave_ibss = iwm_cfg80211_leave_ibss,
556 .set_tx_power = iwm_cfg80211_set_txpower,
557 .get_tx_power = iwm_cfg80211_get_txpower,
558 .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
561 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
564 struct wireless_dev *wdev;
567 * We're trying to have the following memory
570 * +-------------------------+
572 * +-------------------------+
573 * | struct iwm_priv |
574 * +-------------------------+
575 * | bus private data |
576 * | (e.g. iwm_priv_sdio) |
577 * +-------------------------+
581 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
583 dev_err(dev, "Couldn't allocate wireless device\n");
584 return ERR_PTR(-ENOMEM);
587 wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
588 sizeof(struct iwm_priv) + sizeof_bus);
590 dev_err(dev, "Couldn't allocate wiphy device\n");
595 set_wiphy_dev(wdev->wiphy, dev);
596 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
597 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
598 BIT(NL80211_IFTYPE_ADHOC);
599 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
600 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
601 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
603 ret = wiphy_register(wdev->wiphy);
605 dev_err(dev, "Couldn't register wiphy device\n");
606 goto out_err_register;
612 wiphy_free(wdev->wiphy);
620 void iwm_wdev_free(struct iwm_priv *iwm)
622 struct wireless_dev *wdev = iwm_to_wdev(iwm);
627 wiphy_unregister(wdev->wiphy);
628 wiphy_free(wdev->wiphy);