Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
[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/wireless.h>
27 #include <linux/ieee80211.h>
28 #include <net/cfg80211.h>
29
30 #include "iwm.h"
31 #include "commands.h"
32 #include "cfg80211.h"
33 #include "debug.h"
34
35 #define RATETAB_ENT(_rate, _rateid, _flags) \
36         {                                                               \
37                 .bitrate        = (_rate),                              \
38                 .hw_value       = (_rateid),                            \
39                 .flags          = (_flags),                             \
40         }
41
42 #define CHAN2G(_channel, _freq, _flags) {                       \
43         .band                   = IEEE80211_BAND_2GHZ,          \
44         .center_freq            = (_freq),                      \
45         .hw_value               = (_channel),                   \
46         .flags                  = (_flags),                     \
47         .max_antenna_gain       = 0,                            \
48         .max_power              = 30,                           \
49 }
50
51 #define CHAN5G(_channel, _flags) {                              \
52         .band                   = IEEE80211_BAND_5GHZ,          \
53         .center_freq            = 5000 + (5 * (_channel)),      \
54         .hw_value               = (_channel),                   \
55         .flags                  = (_flags),                     \
56         .max_antenna_gain       = 0,                            \
57         .max_power              = 30,                           \
58 }
59
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),
73 };
74
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
79
80 static struct ieee80211_channel iwm_2ghz_channels[] = {
81         CHAN2G(1, 2412, 0),
82         CHAN2G(2, 2417, 0),
83         CHAN2G(3, 2422, 0),
84         CHAN2G(4, 2427, 0),
85         CHAN2G(5, 2432, 0),
86         CHAN2G(6, 2437, 0),
87         CHAN2G(7, 2442, 0),
88         CHAN2G(8, 2447, 0),
89         CHAN2G(9, 2452, 0),
90         CHAN2G(10, 2457, 0),
91         CHAN2G(11, 2462, 0),
92         CHAN2G(12, 2467, 0),
93         CHAN2G(13, 2472, 0),
94         CHAN2G(14, 2484, 0),
95 };
96
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),
116         CHAN5G(216, 0),
117 };
118
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,
124 };
125
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,
131 };
132
133 int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
134 {
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;
141         s32 signal;
142         int freq;
143
144         list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
145                 umac_bss = bss->bss;
146                 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
147
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];
152                 else {
153                         IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
154                         return -EINVAL;
155                 }
156
157                 freq = ieee80211_channel_to_frequency(umac_bss->channel);
158                 channel = ieee80211_get_channel(wiphy, freq);
159                 signal = umac_bss->rssi * 100;
160
161                 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
162                                                le16_to_cpu(umac_bss->frame_len),
163                                                signal, GFP_KERNEL))
164                         return -EINVAL;
165         }
166
167         return 0;
168 }
169
170 static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex,
171                                      enum nl80211_iftype type, u32 *flags,
172                                      struct vif_params *params)
173 {
174         struct net_device *ndev;
175         struct wireless_dev *wdev;
176         struct iwm_priv *iwm;
177         u32 old_mode;
178
179         /* we're under RTNL */
180         ndev = __dev_get_by_index(&init_net, ifindex);
181         if (!ndev)
182                 return -ENODEV;
183
184         wdev = ndev->ieee80211_ptr;
185         iwm = ndev_to_iwm(ndev);
186         old_mode = iwm->conf.mode;
187
188         switch (type) {
189         case NL80211_IFTYPE_STATION:
190                 iwm->conf.mode = UMAC_MODE_BSS;
191                 break;
192         case NL80211_IFTYPE_ADHOC:
193                 iwm->conf.mode = UMAC_MODE_IBSS;
194                 break;
195         default:
196                 return -EOPNOTSUPP;
197         }
198
199         wdev->iftype = type;
200
201         if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
202                 return 0;
203
204         iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
205
206         if (iwm->umac_profile_active) {
207                 int ret = iwm_invalidate_mlme_profile(iwm);
208                 if (ret < 0)
209                         IWM_ERR(iwm, "Couldn't invalidate profile\n");
210         }
211
212         return 0;
213 }
214
215 static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
216                              struct cfg80211_scan_request *request)
217 {
218         struct iwm_priv *iwm = ndev_to_iwm(ndev);
219         int ret;
220
221         if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
222                 IWM_ERR(iwm, "Scan while device is not ready\n");
223                 return -EIO;
224         }
225
226         if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
227                 IWM_ERR(iwm, "Scanning already\n");
228                 return -EAGAIN;
229         }
230
231         if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
232                 IWM_ERR(iwm, "Scanning being aborted\n");
233                 return -EAGAIN;
234         }
235
236         set_bit(IWM_STATUS_SCANNING, &iwm->status);
237
238         ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
239         if (ret) {
240                 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
241                 return ret;
242         }
243
244         iwm->scan_request = request;
245         return 0;
246 }
247
248 static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
249 {
250         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
251
252         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
253             (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
254                 int ret;
255
256                 iwm->conf.rts_threshold = wiphy->rts_threshold;
257
258                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
259                                              CFG_RTS_THRESHOLD,
260                                              iwm->conf.rts_threshold);
261                 if (ret < 0)
262                         return ret;
263         }
264
265         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
266             (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
267                 int ret;
268
269                 iwm->conf.frag_threshold = wiphy->frag_threshold;
270
271                 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
272                                              CFG_FRAG_THRESHOLD,
273                                              iwm->conf.frag_threshold);
274                 if (ret < 0)
275                         return ret;
276         }
277
278         return 0;
279 }
280
281 static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
282                                   struct cfg80211_ibss_params *params)
283 {
284         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
285         struct ieee80211_channel *chan = params->channel;
286         struct cfg80211_bss *bss;
287
288         if (!test_bit(IWM_STATUS_READY, &iwm->status))
289                 return -EIO;
290
291         /* UMAC doesn't support creating IBSS network with specified bssid.
292          * This should be removed after we have join only mode supported. */
293         if (params->bssid)
294                 return -EOPNOTSUPP;
295
296         bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
297                                 params->ssid, params->ssid_len);
298         if (!bss) {
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);
303         }
304         /* IBSS join only mode is not supported by UMAC ATM */
305         if (bss) {
306                 cfg80211_put_bss(bss);
307                 return -EOPNOTSUPP;
308         }
309
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);
315
316         if (params->bssid)
317                 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
318
319         return iwm_send_mlme_profile(iwm);
320 }
321
322 static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
323 {
324         struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
325
326         if (iwm->umac_profile_active)
327                 return iwm_invalidate_mlme_profile(iwm);
328
329         return 0;
330 }
331
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,
338 };
339
340 struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
341 {
342         int ret = 0;
343         struct wireless_dev *wdev;
344
345         /*
346          * We're trying to have the following memory
347          * layout:
348          *
349          * +-------------------------+
350          * | struct wiphy            |
351          * +-------------------------+
352          * | struct iwm_priv         |
353          * +-------------------------+
354          * | bus private data        |
355          * | (e.g. iwm_priv_sdio)    |
356          * +-------------------------+
357          *
358          */
359
360         wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
361         if (!wdev) {
362                 dev_err(dev, "Couldn't allocate wireless device\n");
363                 return ERR_PTR(-ENOMEM);
364         }
365
366         wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
367                                 sizeof(struct iwm_priv) + sizeof_bus);
368         if (!wdev->wiphy) {
369                 dev_err(dev, "Couldn't allocate wiphy device\n");
370                 ret = -ENOMEM;
371                 goto out_err_new;
372         }
373
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;
381
382         ret = wiphy_register(wdev->wiphy);
383         if (ret < 0) {
384                 dev_err(dev, "Couldn't register wiphy device\n");
385                 goto out_err_register;
386         }
387
388         return wdev;
389
390  out_err_register:
391         wiphy_free(wdev->wiphy);
392
393  out_err_new:
394         kfree(wdev);
395
396         return ERR_PTR(ret);
397 }
398
399 void iwm_wdev_free(struct iwm_priv *iwm)
400 {
401         struct wireless_dev *wdev = iwm_to_wdev(iwm);
402
403         if (!wdev)
404                 return;
405
406         wiphy_unregister(wdev->wiphy);
407         wiphy_free(wdev->wiphy);
408         kfree(wdev);
409 }