tree-wide: fix assorted typos all over the place
[linux-2.6-block.git] / drivers / net / wireless / ipw2x00 / libipw_module.c
CommitLineData
b453872c
JG
1/*******************************************************************************
2
ebeaddcc 3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
b453872c
JG
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
85d32e7b
JM
8 <j@w1.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
b453872c
JG
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
c1eb2c82 28 Intel Linux Wireless <ilw@linux.intel.com>
b453872c
JG
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
b453872c
JG
34#include <linux/errno.h>
35#include <linux/if_arp.h>
36#include <linux/in6.h>
37#include <linux/in.h>
38#include <linux/ip.h>
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/netdevice.h>
b453872c
JG
42#include <linux/proc_fs.h>
43#include <linux/skbuff.h>
44#include <linux/slab.h>
45#include <linux/tcp.h>
46#include <linux/types.h>
b453872c
JG
47#include <linux/wireless.h>
48#include <linux/etherdevice.h>
49#include <asm/uaccess.h>
457c4cbc 50#include <net/net_namespace.h>
b453872c
JG
51#include <net/arp.h>
52
b0a4e7d8 53#include "libipw.h"
b453872c 54
31696160
JK
55#define DRV_DESCRIPTION "802.11 data/management/control stack"
56#define DRV_NAME "ieee80211"
b0a4e7d8 57#define DRV_VERSION LIBIPW_VERSION
31696160
JK
58#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
59
60MODULE_VERSION(DRV_VERSION);
61MODULE_DESCRIPTION(DRV_DESCRIPTION);
62MODULE_AUTHOR(DRV_COPYRIGHT);
b453872c
JG
63MODULE_LICENSE("GPL");
64
b8ecd988
JL
65struct cfg80211_ops libipw_config_ops = { };
66void *libipw_wiphy_privid = &libipw_wiphy_privid;
67
b0a4e7d8 68static int libipw_networks_allocate(struct libipw_device *ieee)
b453872c
JG
69{
70 if (ieee->networks)
71 return 0;
72
0edd5b44 73 ieee->networks =
b0a4e7d8 74 kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network),
0edd5b44 75 GFP_KERNEL);
b453872c
JG
76 if (!ieee->networks) {
77 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
78 ieee->dev->name);
79 return -ENOMEM;
80 }
81
b453872c
JG
82 return 0;
83}
84
b0a4e7d8 85void libipw_network_reset(struct libipw_network *network)
15f38598
ZY
86{
87 if (!network)
88 return;
89
90 if (network->ibss_dfs) {
91 kfree(network->ibss_dfs);
92 network->ibss_dfs = NULL;
93 }
94}
95
b0a4e7d8 96static inline void libipw_networks_free(struct libipw_device *ieee)
b453872c 97{
15f38598
ZY
98 int i;
99
b453872c
JG
100 if (!ieee->networks)
101 return;
15f38598
ZY
102
103 for (i = 0; i < MAX_NETWORK_COUNT; i++)
104 if (ieee->networks[i].ibss_dfs)
105 kfree(ieee->networks[i].ibss_dfs);
106
b453872c
JG
107 kfree(ieee->networks);
108 ieee->networks = NULL;
109}
110
b0a4e7d8 111void libipw_networks_age(struct libipw_device *ieee,
c3d72b96
DW
112 unsigned long age_secs)
113{
b0a4e7d8 114 struct libipw_network *network = NULL;
c3d72b96
DW
115 unsigned long flags;
116 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
117
118 spin_lock_irqsave(&ieee->lock, flags);
119 list_for_each_entry(network, &ieee->network_list, list) {
120 network->last_scanned -= age_jiffies;
121 }
122 spin_unlock_irqrestore(&ieee->lock, flags);
123}
b0a4e7d8 124EXPORT_SYMBOL(libipw_networks_age);
c3d72b96 125
b0a4e7d8 126static void libipw_networks_initialize(struct libipw_device *ieee)
b453872c
JG
127{
128 int i;
129
130 INIT_LIST_HEAD(&ieee->network_free_list);
131 INIT_LIST_HEAD(&ieee->network_list);
132 for (i = 0; i < MAX_NETWORK_COUNT; i++)
0edd5b44
JG
133 list_add_tail(&ieee->networks[i].list,
134 &ieee->network_free_list);
b453872c
JG
135}
136
b0a4e7d8 137int libipw_change_mtu(struct net_device *dev, int new_mtu)
42a4cf95 138{
b0a4e7d8 139 if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
42a4cf95 140 return -EINVAL;
141 dev->mtu = new_mtu;
142 return 0;
143}
b0a4e7d8 144EXPORT_SYMBOL(libipw_change_mtu);
42a4cf95 145
b8ecd988 146struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
b453872c 147{
b0a4e7d8 148 struct libipw_device *ieee;
b453872c
JG
149 struct net_device *dev;
150 int err;
151
b0a4e7d8 152 LIBIPW_DEBUG_INFO("Initializing...\n");
b453872c 153
b0a4e7d8 154 dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
b453872c 155 if (!dev) {
b0a4e7d8 156 LIBIPW_ERROR("Unable to allocate network device.\n");
b453872c
JG
157 goto failed;
158 }
159 ieee = netdev_priv(dev);
b453872c
JG
160
161 ieee->dev = dev;
162
b8ecd988
JL
163 if (!monitor) {
164 ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
165 if (!ieee->wdev.wiphy) {
166 LIBIPW_ERROR("Unable to allocate wiphy.\n");
167 goto failed_free_netdev;
168 }
169
170 ieee->dev->ieee80211_ptr = &ieee->wdev;
171 ieee->wdev.iftype = NL80211_IFTYPE_STATION;
172
173 /* Fill-out wiphy structure bits we know... Not enough info
174 here to call set_wiphy_dev or set MAC address or channel info
175 -- have to do that in ->ndo_init... */
176 ieee->wdev.wiphy->privid = libipw_wiphy_privid;
177
178 ieee->wdev.wiphy->max_scan_ssids = 1;
179 ieee->wdev.wiphy->max_scan_ie_len = 0;
180 ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
181 | BIT(NL80211_IFTYPE_ADHOC);
182 }
183
b0a4e7d8 184 err = libipw_networks_allocate(ieee);
b453872c 185 if (err) {
b0a4e7d8 186 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
b8ecd988 187 goto failed_free_wiphy;
b453872c 188 }
b0a4e7d8 189 libipw_networks_initialize(ieee);
b453872c
JG
190
191 /* Default fragmentation threshold is maximum payload size */
192 ieee->fts = DEFAULT_FTS;
3cdd00c5 193 ieee->rts = DEFAULT_FTS;
b453872c
JG
194 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
195 ieee->open_wep = 1;
196
197 /* Default to enabling full open WEP with host based encrypt/decrypt */
198 ieee->host_encrypt = 1;
199 ieee->host_decrypt = 1;
ccd0fda3
JK
200 ieee->host_mc_decrypt = 1;
201
af901ca1 202 /* Host fragmentation in Open mode. Default is enabled.
1264fc04
JK
203 * Note: host fragmentation is always enabled if host encryption
204 * is enabled. For cards can do hardware encryption, they must do
205 * hardware fragmentation as well. So we don't need a variable
206 * like host_enc_frag. */
207 ieee->host_open_frag = 1;
0edd5b44 208 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c 209
b453872c
JG
210 spin_lock_init(&ieee->lock);
211
2ba4b32e 212 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
274bfb8d 213
0edd5b44 214 ieee->wpa_enabled = 0;
0edd5b44
JG
215 ieee->drop_unencrypted = 0;
216 ieee->privacy_invoked = 0;
b453872c
JG
217
218 return dev;
219
b8ecd988
JL
220failed_free_wiphy:
221 if (!monitor)
222 wiphy_free(ieee->wdev.wiphy);
d92a8e81
JL
223failed_free_netdev:
224 free_netdev(dev);
225failed:
b453872c
JG
226 return NULL;
227}
228
b8ecd988 229void free_ieee80211(struct net_device *dev, int monitor)
b453872c 230{
b0a4e7d8 231 struct libipw_device *ieee = netdev_priv(dev);
b453872c 232
2ba4b32e 233 lib80211_crypt_info_free(&ieee->crypt_info);
b453872c 234
b0a4e7d8 235 libipw_networks_free(ieee);
b8ecd988
JL
236
237 /* free cfg80211 resources */
e6c5fc53 238 if (!monitor)
b8ecd988 239 wiphy_free(ieee->wdev.wiphy);
b8ecd988 240
b453872c
JG
241 free_netdev(dev);
242}
243
e6c5fc53
ZY
244void unregister_ieee80211(struct libipw_device *ieee)
245{
246 wiphy_unregister(ieee->wdev.wiphy);
247 kfree(ieee->a_band.channels);
248 kfree(ieee->bg_band.channels);
249}
250
3756162b 251#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
252
253static int debug = 0;
b0a4e7d8
JL
254u32 libipw_debug_level = 0;
255EXPORT_SYMBOL_GPL(libipw_debug_level);
256static struct proc_dir_entry *libipw_proc = NULL;
b453872c
JG
257
258static int show_debug_level(char *page, char **start, off_t offset,
259 int count, int *eof, void *data)
260{
b0a4e7d8 261 return snprintf(page, count, "0x%08X\n", libipw_debug_level);
b453872c
JG
262}
263
0edd5b44 264static int store_debug_level(struct file *file, const char __user * buffer,
b453872c
JG
265 unsigned long count, void *data)
266{
262d8e46
JK
267 char buf[] = "0x00000000\n";
268 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
b453872c
JG
269 unsigned long val;
270
262d8e46 271 if (copy_from_user(buf, buffer, len))
b453872c 272 return count;
262d8e46
JK
273 buf[len] = 0;
274 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
275 printk(KERN_INFO DRV_NAME
276 ": %s is not in hex or decimal form.\n", buf);
277 else
b0a4e7d8 278 libipw_debug_level = val;
b453872c 279
262d8e46 280 return strnlen(buf, len);
b453872c 281}
3756162b 282#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 283
b0a4e7d8 284static int __init libipw_init(void)
b453872c 285{
3756162b 286#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
287 struct proc_dir_entry *e;
288
b0a4e7d8
JL
289 libipw_debug_level = debug;
290 libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
291 if (libipw_proc == NULL) {
292 LIBIPW_ERROR("Unable to create " DRV_NAME
b453872c
JG
293 " proc directory\n");
294 return -EIO;
295 }
296 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
b0a4e7d8 297 libipw_proc);
b453872c 298 if (!e) {
457c4cbc 299 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 300 libipw_proc = NULL;
b453872c
JG
301 return -EIO;
302 }
303 e->read_proc = show_debug_level;
304 e->write_proc = store_debug_level;
305 e->data = NULL;
3756162b 306#endif /* CONFIG_LIBIPW_DEBUG */
31696160
JK
307
308 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
309 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
310
311 return 0;
312}
313
b0a4e7d8 314static void __exit libipw_exit(void)
b453872c 315{
3756162b 316#ifdef CONFIG_LIBIPW_DEBUG
b0a4e7d8
JL
317 if (libipw_proc) {
318 remove_proc_entry("debug_level", libipw_proc);
457c4cbc 319 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 320 libipw_proc = NULL;
b453872c 321 }
3756162b 322#endif /* CONFIG_LIBIPW_DEBUG */
b453872c
JG
323}
324
3756162b 325#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
326#include <linux/moduleparam.h>
327module_param(debug, int, 0444);
328MODULE_PARM_DESC(debug, "debug output mask");
3756162b 329#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 330
b0a4e7d8
JL
331module_exit(libipw_exit);
332module_init(libipw_init);
b453872c
JG
333
334EXPORT_SYMBOL(alloc_ieee80211);
335EXPORT_SYMBOL(free_ieee80211);
e6c5fc53 336EXPORT_SYMBOL(unregister_ieee80211);