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/wireless.h>
27 #include <linux/ieee80211.h>
28 #include <net/cfg80211.h>
35 #define RATETAB_ENT(_rate, _rateid, _flags) \
38 .hw_value = (_rateid), \
42 #define CHAN2G(_channel, _freq, _flags) { \
43 .band = IEEE80211_BAND_2GHZ, \
44 .center_freq = (_freq), \
45 .hw_value = (_channel), \
47 .max_antenna_gain = 0, \
51 #define CHAN5G(_channel, _flags) { \
52 .band = IEEE80211_BAND_5GHZ, \
53 .center_freq = 5000 + (5 * (_channel)), \
54 .hw_value = (_channel), \
56 .max_antenna_gain = 0, \
60 static struct ieee80211_rate iwm_rates[] = {
61 RATETAB_ENT(10, 0x1, 0),
62 RATETAB_ENT(20, 0x2, 0),
63 RATETAB_ENT(55, 0x4, 0),
64 RATETAB_ENT(110, 0x8, 0),
65 RATETAB_ENT(60, 0x10, 0),
66 RATETAB_ENT(90, 0x20, 0),
67 RATETAB_ENT(120, 0x40, 0),
68 RATETAB_ENT(180, 0x80, 0),
69 RATETAB_ENT(240, 0x100, 0),
70 RATETAB_ENT(360, 0x200, 0),
71 RATETAB_ENT(480, 0x400, 0),
72 RATETAB_ENT(540, 0x800, 0),
75 #define iwm_a_rates (iwm_rates + 4)
76 #define iwm_a_rates_size 8
77 #define iwm_g_rates (iwm_rates + 0)
78 #define iwm_g_rates_size 12
80 static struct ieee80211_channel iwm_2ghz_channels[] = {
97 static struct ieee80211_channel iwm_5ghz_a_channels[] = {
98 CHAN5G(34, 0), CHAN5G(36, 0),
99 CHAN5G(38, 0), CHAN5G(40, 0),
100 CHAN5G(42, 0), CHAN5G(44, 0),
101 CHAN5G(46, 0), CHAN5G(48, 0),
102 CHAN5G(52, 0), CHAN5G(56, 0),
103 CHAN5G(60, 0), CHAN5G(64, 0),
104 CHAN5G(100, 0), CHAN5G(104, 0),
105 CHAN5G(108, 0), CHAN5G(112, 0),
106 CHAN5G(116, 0), CHAN5G(120, 0),
107 CHAN5G(124, 0), CHAN5G(128, 0),
108 CHAN5G(132, 0), CHAN5G(136, 0),
109 CHAN5G(140, 0), CHAN5G(149, 0),
110 CHAN5G(153, 0), CHAN5G(157, 0),
111 CHAN5G(161, 0), CHAN5G(165, 0),
112 CHAN5G(184, 0), CHAN5G(188, 0),
113 CHAN5G(192, 0), CHAN5G(196, 0),
114 CHAN5G(200, 0), CHAN5G(204, 0),
115 CHAN5G(208, 0), CHAN5G(212, 0),
119 static struct ieee80211_supported_band iwm_band_2ghz = {
120 .channels = iwm_2ghz_channels,
121 .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
122 .bitrates = iwm_g_rates,
123 .n_bitrates = iwm_g_rates_size,
126 static struct ieee80211_supported_band iwm_band_5ghz = {
127 .channels = iwm_5ghz_a_channels,
128 .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
129 .bitrates = iwm_a_rates,
130 .n_bitrates = iwm_a_rates_size,
133 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
135 struct wiphy *wiphy = iwm_to_wiphy(iwm);
136 struct iwm_bss_info *bss, *next;
137 struct iwm_umac_notif_bss_info *umac_bss;
138 struct ieee80211_mgmt *mgmt;
139 struct ieee80211_channel *channel;
140 struct ieee80211_supported_band *band;
144 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
146 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
148 if (umac_bss->band == UMAC_BAND_2GHZ)
149 band = wiphy->bands[IEEE80211_BAND_2GHZ];
150 else if (umac_bss->band == UMAC_BAND_5GHZ)
151 band = wiphy->bands[IEEE80211_BAND_5GHZ];
153 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
157 freq = ieee80211_channel_to_frequency(umac_bss->channel);
158 channel = ieee80211_get_channel(wiphy, freq);
159 signal = umac_bss->rssi * 100;
161 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
162 le16_to_cpu(umac_bss->frame_len),
170 static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex,
171 enum nl80211_iftype type, u32 *flags,
172 struct vif_params *params)
174 struct net_device *ndev;
175 struct wireless_dev *wdev;
176 struct iwm_priv *iwm;
179 /* we're under RTNL */
180 ndev = __dev_get_by_index(&init_net, ifindex);
184 wdev = ndev->ieee80211_ptr;
185 iwm = ndev_to_iwm(ndev);
186 old_mode = iwm->conf.mode;
189 case NL80211_IFTYPE_STATION:
190 iwm->conf.mode = UMAC_MODE_BSS;
192 case NL80211_IFTYPE_ADHOC:
193 iwm->conf.mode = UMAC_MODE_IBSS;
201 if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
204 iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
206 if (iwm->umac_profile_active) {
207 int ret = iwm_invalidate_mlme_profile(iwm);
209 IWM_ERR(iwm, "Couldn't invalidate profile\n");
215 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
216 struct cfg80211_scan_request *request)
218 struct iwm_priv *iwm = ndev_to_iwm(ndev);
221 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
222 IWM_ERR(iwm, "Scan while device is not ready\n");
226 if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
227 IWM_ERR(iwm, "Scanning already\n");
231 if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
232 IWM_ERR(iwm, "Scanning being aborted\n");
236 set_bit(IWM_STATUS_SCANNING, &iwm->status);
238 ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
240 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
244 iwm->scan_request = request;
248 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
250 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
252 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
253 (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
256 iwm->conf.rts_threshold = wiphy->rts_threshold;
258 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
260 iwm->conf.rts_threshold);
265 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
266 (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
269 iwm->conf.frag_threshold = wiphy->frag_threshold;
271 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
273 iwm->conf.frag_threshold);
281 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
282 struct cfg80211_ibss_params *params)
284 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
285 struct ieee80211_channel *chan = params->channel;
286 struct cfg80211_bss *bss;
288 if (!test_bit(IWM_STATUS_READY, &iwm->status))
291 /* UMAC doesn't support creating IBSS network with specified bssid.
292 * This should be removed after we have join only mode supported. */
296 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
297 params->ssid, params->ssid_len);
299 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
300 schedule_timeout_interruptible(2 * HZ);
301 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
302 params->ssid, params->ssid_len);
304 /* IBSS join only mode is not supported by UMAC ATM */
306 cfg80211_put_bss(bss);
310 iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
311 iwm->umac_profile->ibss.band = chan->band;
312 iwm->umac_profile->ibss.channel = iwm->channel;
313 iwm->umac_profile->ssid.ssid_len = params->ssid_len;
314 memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
317 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
319 return iwm_send_mlme_profile(iwm);
322 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
324 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
326 if (iwm->umac_profile_active)
327 return iwm_invalidate_mlme_profile(iwm);
332 static struct cfg80211_ops iwm_cfg80211_ops = {
333 .change_virtual_intf = iwm_cfg80211_change_iface,
334 .scan = iwm_cfg80211_scan,
335 .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
336 .join_ibss = iwm_cfg80211_join_ibss,
337 .leave_ibss = iwm_cfg80211_leave_ibss,
340 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
343 struct wireless_dev *wdev;
346 * We're trying to have the following memory
349 * +-------------------------+
351 * +-------------------------+
352 * | struct iwm_priv |
353 * +-------------------------+
354 * | bus private data |
355 * | (e.g. iwm_priv_sdio) |
356 * +-------------------------+
360 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
362 dev_err(dev, "Couldn't allocate wireless device\n");
363 return ERR_PTR(-ENOMEM);
366 wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
367 sizeof(struct iwm_priv) + sizeof_bus);
369 dev_err(dev, "Couldn't allocate wiphy device\n");
374 set_wiphy_dev(wdev->wiphy, dev);
375 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
376 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
377 BIT(NL80211_IFTYPE_ADHOC);
378 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
379 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
380 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
382 ret = wiphy_register(wdev->wiphy);
384 dev_err(dev, "Couldn't register wiphy device\n");
385 goto out_err_register;
391 wiphy_free(wdev->wiphy);
399 void iwm_wdev_free(struct iwm_priv *iwm)
401 struct wireless_dev *wdev = iwm_to_wdev(iwm);
406 wiphy_unregister(wdev->wiphy);
407 wiphy_free(wdev->wiphy);